tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

memleak.sh (23339B)


      1 #!/bin/bash
      2 #
      3 # This Source Code Form is subject to the terms of the Mozilla Public
      4 # License, v. 2.0. If a copy of the MPL was not distributed with this
      5 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
      6 
      7 ########################################################################
      8 #
      9 # mozilla/security/nss/tests/memleak/memleak.sh
     10 #
     11 # Script to test memory leaks in NSS
     12 #
     13 # needs to work on Solaris and Linux platforms, on others just print a message
     14 # that OS is not supported
     15 #
     16 # special strings
     17 # ---------------
     18 #   FIXME ... known problems, search for this string
     19 #   NOTE .... unexpected behavior
     20 #
     21 ########################################################################
     22 
     23 ############################# memleak_init #############################
     24 # local shell function to initialize this script 
     25 ########################################################################
     26 memleak_init()
     27 {
     28 if [ -z "${INIT_SOURCED}" -o "${INIT_SOURCED}" != "TRUE" ]; then
     29 	cd ../common
     30 	. ./init.sh
     31 fi
     32 
     33 if [ ! -r ${CERT_LOG_FILE} ]; then
     34 	cd ${QADIR}/cert
     35 	. ./cert.sh
     36 fi
     37 
     38 SCRIPTNAME="memleak.sh"
     39 if [ -z "${CLEANUP}" ] ; then
     40 	CLEANUP="${SCRIPTNAME}"
     41 fi
     42 
     43 OLD_LIBRARY_PATH=${LD_LIBRARY_PATH}
     44 TMP_LIBDIR="${HOSTDIR}/tmp"
     45 TMP_STACKS="${HOSTDIR}/stacks"
     46 TMP_SORTED="${HOSTDIR}/sorted"
     47 TMP_COUNT="${HOSTDIR}/count"
     48 DBXOUT="${HOSTDIR}/dbxout"
     49 DBXERR="${HOSTDIR}/dbxerr"
     50 DBXCMD="${HOSTDIR}/dbxcmd"
     51 
     52 PORT=${PORT:-8443}
     53 
     54 MODE_LIST="NORMAL BYPASS FIPS"
     55 
     56 SERVER_DB="${HOSTDIR}/server_memleak"
     57 CLIENT_DB="${HOSTDIR}/client_memleak"
     58 cp -r ${HOSTDIR}/server ${SERVER_DB}
     59 cp -r ${HOSTDIR}/client ${CLIENT_DB}
     60 
     61 LOGDIR="${HOSTDIR}/memleak_logs"
     62 mkdir -p ${LOGDIR}
     63 
     64 FOUNDLEAKS="${LOGDIR}/foundleaks"
     65 
     66 REQUEST_FILE="${QADIR}/memleak/sslreq.dat"
     67 IGNORED_STACKS="${QADIR}/memleak/ignored"
     68 
     69 gline=`echo ${OBJDIR} | grep "_64_"`
     70 if [ -n "${gline}" ] ; then
     71 	BIT_NAME="64"
     72 else
     73 	BIT_NAME="32"
     74 fi
     75 	
     76 case "${OS_NAME}" in
     77 "SunOS")
     78 	DBX=`which dbx`
     79 	AWK=nawk
     80 	
     81 	if [ $? -eq 0 ] ; then
     82 		echo "${SCRIPTNAME}: DBX found: ${DBX}"
     83 	else
     84 		echo "${SCRIPTNAME}: DBX not found, skipping memory leak checking."
     85 		exit 0
     86 	fi
     87 	
     88 	PROC_ARCH=`uname -p`
     89 			
     90 	if [ "${PROC_ARCH}" = "sparc" ] ; then
     91 		if [ "${BIT_NAME}" = "64" ] ; then
     92 			FREEBL_DEFAULT="libfreebl_64fpu_3"
     93 			FREEBL_LIST="${FREEBL_DEFAULT} libfreebl_64int_3"
     94 		else
     95 			FREEBL_DEFAULT="libfreebl_32fpu_3"
     96 			FREEBL_LIST="${FREEBL_DEFAULT} libfreebl_32int64_3"
     97 		fi
     98 	else
     99 		if [ "${BIT_NAME}" = "64" ] ; then
    100 			echo "${SCRIPTNAME}: OS not supported for memory leak checking."
    101 			exit 0
    102 		fi
    103 		
    104 		FREEBL_DEFAULT="libfreebl_3"
    105 		FREEBL_LIST="${FREEBL_DEFAULT}"
    106 	fi
    107 	
    108 	RUN_COMMAND_DBG="run_command_dbx"
    109 	PARSE_LOGFILE="parse_logfile_dbx"
    110 	;;
    111 "Linux")
    112 	VALGRIND=`which valgrind`
    113 	AWK=awk
    114 	
    115 	if [ $? -eq 0 ] ; then
    116 		echo "${SCRIPTNAME}: Valgrind found: ${VALGRIND}"
    117 	else
    118 		echo "${SCRIPTNAME}: Valgrind not found, skipping memory leak checking."
    119 		exit 0
    120 	fi
    121 
    122 	FREEBL_DEFAULT="libfreebl_3"
    123 	FREEBL_LIST="${FREEBL_DEFAULT}"
    124 			
    125 	RUN_COMMAND_DBG="run_command_valgrind"
    126 	PARSE_LOGFILE="parse_logfile_valgrind"
    127 	;;
    128 *)
    129 	echo "${SCRIPTNAME}: OS not supported for memory leak checking."
    130 	exit 0
    131 	;;
    132 esac
    133 
    134 if [ "${BUILD_OPT}" = "1" ] ; then
    135 	OPT="OPT"
    136 else 
    137 	OPT="DBG"
    138 fi
    139 
    140 NSS_DISABLE_UNLOAD="1"
    141 export NSS_DISABLE_UNLOAD
    142 
    143 SELFSERV_ATTR="-D -p ${PORT} -d ${SERVER_DB} -n ${HOSTADDR} -e ${HOSTADDR}-ec -w nss -c :C001:C002:C003:C004:C005:C006:C007:C008:C009:C00A:C00B:C00C:C00D:C00E:C00F:C010:C011:C012:C013:C014cdefgijklmnvyz -t 5 -V ssl3:tls1.2"
    144 TSTCLNT_ATTR="-p ${PORT} -h ${HOSTADDR} -c j -f -d ${CLIENT_DB} -w nss -o"
    145 STRSCLNT_ATTR="-q -p ${PORT} -d ${CLIENT_DB} -w nss -c 1000 -n TestUser ${HOSTADDR}"
    146 
    147 tbytes=0
    148 tblocks=0
    149 truns=0
    150 
    151 MEMLEAK_DBG=1
    152 export MEMLEAK_DBG
    153 }
    154 
    155 ########################### memleak_cleanup ############################
    156 # local shell function to clean up after this script 
    157 ########################################################################
    158 memleak_cleanup()
    159 {
    160 unset MEMLEAK_DBG
    161 unset NSS_DISABLE_UNLOAD
    162 
    163 . ${QADIR}/common/cleanup.sh
    164 }
    165 
    166 ############################ set_test_mode #############################
    167 # local shell function to set testing mode for server and for client
    168 ########################################################################
    169 set_test_mode()
    170 {
    171 if [ "${server_mode}" = "BYPASS" ] ; then
    172 	echo "${SCRIPTNAME}: BYPASS is ON"
    173 	SERVER_OPTION="-B -s"
    174 	CLIENT_OPTION=""
    175 elif [ "${client_mode}" = "BYPASS" ] ; then
    176 	echo "${SCRIPTNAME}: BYPASS is ON"
    177 	SERVER_OPTION=""
    178 	CLIENT_OPTION="-B -s"
    179 else
    180 	echo "${SCRIPTNAME}: BYPASS is OFF"
    181 	SERVER_OPTION=""
    182 	CLIENT_OPTION=""
    183 fi
    184 
    185 if [ "${server_mode}" = "FIPS" ] ; then
    186 	${BINDIR}/modutil -dbdir ${SERVER_DB} -fips true -force
    187 	${BINDIR}/modutil -dbdir ${SERVER_DB} -list
    188 	${BINDIR}/modutil -dbdir ${CLIENT_DB} -fips false -force
    189 	${BINDIR}/modutil -dbdir ${CLIENT_DB} -list
    190 	
    191 	echo "${SCRIPTNAME}: FIPS is ON"
    192 	cipher_list="c d e i j k n v y z"
    193 elif [ "${client_mode}" = "FIPS" ] ; then
    194 	
    195 	${BINDIR}/modutil -dbdir ${SERVER_DB} -fips false -force
    196 	${BINDIR}/modutil -dbdir ${SERVER_DB} -list
    197 	${BINDIR}/modutil -dbdir ${CLIENT_DB} -fips true -force
    198 	${BINDIR}/modutil -dbdir ${CLIENT_DB} -list
    199 	
    200 	echo "${SCRIPTNAME}: FIPS is ON"
    201 	cipher_list="c d e i j k n v y z"
    202 else
    203 	${BINDIR}/modutil -dbdir ${SERVER_DB} -fips false -force
    204 	${BINDIR}/modutil -dbdir ${SERVER_DB} -list
    205 	${BINDIR}/modutil -dbdir ${CLIENT_DB} -fips false -force
    206 	${BINDIR}/modutil -dbdir ${CLIENT_DB} -list
    207 	
    208 	echo "${SCRIPTNAME}: FIPS is OFF"
    209 	# ciphers l and m removed, see bug 1136095
    210 	cipher_list=":C001 :C002 :C003 :C004 :C005 :C006 :C007 :C008 :C009 :C00A :C010 :C011 :C012 :C013 :C014 c d e f g i j k n v y z"
    211 fi
    212 }
    213 
    214 ############################## set_freebl ##############################
    215 # local shell function to set freebl - sets temporary path for libraries
    216 ########################################################################
    217 set_freebl()
    218 {
    219 if [ "${freebl}" = "${FREEBL_DEFAULT}" ] ; then
    220 	LD_LIBRARY_PATH="${OLD_LIBRARY_PATH}"
    221 	export LD_LIBRARY_PATH
    222 else
    223 	if [ -d "${TMP_LIBDIR}" ] ; then
    224 		rm -rf ${TMP_LIBDIR}
    225 	fi
    226 
    227 	mkdir ${TMP_LIBDIR}
    228 	[ $? -ne 0 ] && html_failed "Create temp directory" && return 1
    229 
    230 	cp ${DIST}/${OBJDIR}/lib/*.so ${DIST}/${OBJDIR}/lib/*.chk ${TMP_LIBDIR}
    231 	[ $? -ne 0 ] && html_failed "Copy libraries to temp directory" && return 1
    232 	
    233 	echo "${SCRIPTNAME}: Using ${freebl} instead of ${FREEBL_DEFAULT}"
    234 
    235 	mv ${TMP_LIBDIR}/${FREEBL_DEFAULT}.so ${TMP_LIBDIR}/${FREEBL_DEFAULT}.so.orig
    236 	[ $? -ne 0 ] && html_failed "Move ${FREEBL_DEFAULT}.so -> ${FREEBL_DEFAULT}.so.orig" && return 1
    237 
    238 	cp ${TMP_LIBDIR}/${freebl}.so ${TMP_LIBDIR}/${FREEBL_DEFAULT}.so
    239 	[ $? -ne 0 ] && html_failed "Copy ${freebl}.so -> ${FREEBL_DEFAULT}.so" && return 1
    240 
    241 	mv ${TMP_LIBDIR}/${FREEBL_DEFAULT}.chk ${TMP_LIBDIR}/${FREEBL_DEFAULT}.chk.orig
    242 	[ $? -ne 0 ] && html_failed "Move ${FREEBL_DEFAULT}.chk -> ${FREEBL_DEFAULT}.chk.orig" && return 1
    243 
    244 	cp ${TMP_LIBDIR}/${freebl}.chk ${TMP_LIBDIR}/${FREEBL_DEFAULT}.chk
    245 	[ $? -ne 0 ] && html_failed "Copy ${freebl}.chk to temp directory" && return 1
    246 
    247 	echo "ls -l ${TMP_LIBDIR}"
    248 	ls -l ${TMP_LIBDIR}
    249 
    250 	LD_LIBRARY_PATH="${TMP_LIBDIR}"
    251 	export LD_LIBRARY_PATH
    252 fi
    253 
    254 return 0
    255 }
    256 
    257 ############################# clear_freebl #############################
    258 # local shell function to set default library path and clear temporary 
    259 # directory for libraries created by function set_freebl 
    260 ########################################################################
    261 clear_freebl()
    262 {
    263 LD_LIBRARY_PATH="${OLD_LIBRARY_PATH}"
    264 export LD_LIBRARY_PATH
    265 
    266 if [ -d "${TMP_LIBDIR}" ] ; then
    267 	rm -rf ${TMP_LIBDIR}
    268 fi
    269 }
    270 
    271 ############################ run_command_dbx ###########################
    272 # local shell function to run command under dbx tool
    273 ########################################################################
    274 run_command_dbx()
    275 {
    276 COMMAND=$1
    277 shift
    278 ATTR=$*
    279 
    280 COMMAND=`which ${COMMAND}`
    281 
    282 echo "dbxenv follow_fork_mode parent" > ${DBXCMD}
    283 echo "dbxenv rtc_mel_at_exit verbose" >> ${DBXCMD}
    284 echo "dbxenv rtc_biu_at_exit verbose" >> ${DBXCMD}
    285 echo "check -memuse -match 16 -frames 16" >> ${DBXCMD}
    286 echo "run ${ATTR}" >> ${DBXCMD}
    287 
    288 export NSS_DISABLE_ARENA_FREE_LIST=1
    289 
    290 echo "${SCRIPTNAME}: -------- Running ${COMMAND} under DBX:"
    291 echo "${DBX} ${COMMAND}"
    292 echo "${SCRIPTNAME}: -------- DBX commands:"
    293 cat ${DBXCMD}
    294 
    295 ( ${DBX} ${COMMAND} < ${DBXCMD} > ${DBXOUT} 2> ${DBXERR} )
    296 grep -v Reading ${DBXOUT} 1>&2
    297 cat ${DBXERR}
    298 
    299 unset NSS_DISABLE_ARENA_FREE_LIST
    300 
    301 grep "exit code is" ${DBXOUT}
    302 grep "exit code is 0" ${DBXOUT} > /dev/null
    303 return $?
    304 }
    305 
    306 ######################### run_command_valgrind #########################
    307 # local shell function to run command under valgrind tool
    308 ########################################################################
    309 run_command_valgrind()
    310 {
    311 COMMAND=$1
    312 shift
    313 ATTR=$*
    314 
    315 export NSS_DISABLE_ARENA_FREE_LIST=1
    316 
    317 echo "${SCRIPTNAME}: -------- Running ${COMMAND} under Valgrind:"
    318 echo "${VALGRIND} --tool=memcheck --leak-check=yes --show-reachable=yes --partial-loads-ok=yes --leak-resolution=high --num-callers=50 ${COMMAND} ${ATTR}"
    319 echo "Running: ${COMMAND} ${ATTR}" 1>&2
    320 ${VALGRIND} --tool=memcheck --leak-check=yes --show-reachable=yes --partial-loads-ok=yes --leak-resolution=high --num-callers=50 ${COMMAND} ${ATTR} 1>&2
    321 ret=$?
    322 echo "==0=="
    323 
    324 unset NSS_DISABLE_ARENA_FREE_LIST
    325 
    326 return $ret
    327 }
    328 
    329 ############################# run_selfserv #############################
    330 # local shell function to start selfserv
    331 ########################################################################
    332 run_selfserv()
    333 {
    334 echo "PATH=${PATH}"
    335 echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}"
    336 echo "${SCRIPTNAME}: -------- Running selfserv:"
    337 echo "selfserv ${SELFSERV_ATTR}"
    338 ${BINDIR}/selfserv ${SELFSERV_ATTR}
    339 ret=$?
    340 if [ $ret -ne 0 ]; then
    341 	html_failed "${LOGNAME}: Selfserv"
    342 	echo "${SCRIPTNAME} ${LOGNAME}: " \
    343 		"Selfserv produced a returncode of ${ret} - FAILED"
    344 fi
    345 }
    346 
    347 ########################### run_selfserv_dbg ###########################
    348 # local shell function to start selfserv under debug tool
    349 ########################################################################
    350 run_selfserv_dbg()
    351 {
    352 echo "PATH=${PATH}"
    353 echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}"
    354 ${RUN_COMMAND_DBG} ${BINDIR}/selfserv ${SERVER_OPTION} ${SELFSERV_ATTR}
    355 ret=$?
    356 if [ $ret -ne 0 ]; then
    357 	html_failed "${LOGNAME}: Selfserv"
    358 	echo "${SCRIPTNAME} ${LOGNAME}: " \
    359 		"Selfserv produced a returncode of ${ret} - FAILED"
    360 fi
    361 }
    362 
    363 ############################# run_strsclnt #############################
    364 # local shell function to run strsclnt for all ciphers and send stop
    365 # command to selfserv over tstclnt
    366 ########################################################################
    367 run_strsclnt()
    368 {
    369 for cipher in ${cipher_list}; do
    370 	VMIN="ssl3"
    371 	VMAX="tls1.2"
    372 	case "${cipher}" in
    373 	f|g)
    374 		# TLS 1.1 disallows export cipher suites.
    375 		VMAX="tls1.0"
    376 		;;
    377 	esac
    378 	ATTR="${STRSCLNT_ATTR} -C ${cipher} -V ${VMIN}:${VMAX}"
    379 	echo "${SCRIPTNAME}: -------- Trying cipher ${cipher}:"
    380 	echo "strsclnt ${ATTR}"
    381 	${BINDIR}/strsclnt ${ATTR}
    382 	ret=$?
    383 	if [ $ret -ne 0 ]; then
    384 		html_failed "${LOGNAME}: Strsclnt with cipher ${cipher}"
    385 		echo "${SCRIPTNAME} ${LOGNAME}: " \
    386 			"Strsclnt produced a returncode of ${ret} - FAILED"
    387 	fi
    388 done
    389 
    390 ATTR="${TSTCLNT_ATTR} -V ssl3:tls1.2"
    391 echo "${SCRIPTNAME}: -------- Stopping server:"
    392 echo "tstclnt ${ATTR} < ${REQUEST_FILE}"
    393 ${BINDIR}/tstclnt ${ATTR} < ${REQUEST_FILE}
    394 ret=$?
    395 if [ $ret -ne 0 ]; then
    396 	html_failed "${LOGNAME}: Tstclnt"
    397 	echo "${SCRIPTNAME} ${LOGNAME}: " \
    398 		"Tstclnt produced a returncode of ${ret} - FAILED"
    399 fi
    400 
    401 sleep 20
    402 kill $(jobs -p) 2> /dev/null
    403 }
    404 
    405 ########################### run_strsclnt_dbg ###########################
    406 # local shell function to run strsclnt under debug tool for all ciphers 
    407 # and send stop command to selfserv over tstclnt
    408 ########################################################################
    409 run_strsclnt_dbg()
    410 {
    411 for cipher in ${cipher_list}; do
    412 	VMIN="ssl3"
    413 	VMAX="tls1.2"
    414 	case "${cipher}" in
    415 	f|g)
    416 		# TLS 1.1 disallows export cipher suites.
    417 		VMAX="tls1.0"
    418 		;;
    419 	esac
    420 	ATTR="${STRSCLNT_ATTR} -C ${cipher} -V ${VMIN}:${VMAX}"
    421 	${RUN_COMMAND_DBG} ${BINDIR}/strsclnt ${CLIENT_OPTION} ${ATTR}
    422 	ret=$?
    423 	if [ $ret -ne 0 ]; then
    424 		html_failed "${LOGNAME}: Strsclnt with cipher ${cipher}"
    425 		echo "${SCRIPTNAME} ${LOGNAME}: " \
    426 			"Strsclnt produced a returncode of ${ret} - FAILED"
    427 	fi
    428 done
    429 
    430 ATTR="${TSTCLNT_ATTR} -V ssl3:tls1.2"
    431 echo "${SCRIPTNAME}: -------- Stopping server:"
    432 echo "tstclnt ${ATTR} < ${REQUEST_FILE}"
    433 ${BINDIR}/tstclnt ${ATTR} < ${REQUEST_FILE}
    434 ret=$?
    435 if [ $ret -ne 0 ]; then
    436 	html_failed "${LOGNAME}: Tstclnt"
    437 	echo "${SCRIPTNAME} ${LOGNAME}: " \
    438 		"Tstclnt produced a returncode of ${ret} - FAILED"
    439 fi
    440 
    441 kill $(jobs -p) 2> /dev/null
    442 }
    443 
    444 stat_clear()
    445 {
    446 stat_minbytes=9999999
    447 stat_maxbytes=0
    448 stat_minblocks=9999999
    449 stat_maxblocks=0
    450 stat_bytes=0
    451 stat_blocks=0
    452 stat_runs=0
    453 }
    454 
    455 stat_add()
    456 {
    457 read hash lbytes bytes_str lblocks blocks_str in_str lruns runs_str \
    458 	minbytes minbytes_str maxbytes maxbytes_str minblocks \
    459 	minblocks_str maxblocks maxblocks_str rest < ${TMP_COUNT} 
    460 rm ${TMP_COUNT}
    461 
    462 tbytes=`expr ${tbytes} + ${lbytes}`
    463 tblocks=`expr ${tblocks} + ${lblocks}`
    464 truns=`expr ${truns} + ${lruns}`
    465 
    466 if [ ${stat_minbytes} -gt ${minbytes} ]; then
    467 	stat_minbytes=${minbytes}
    468 fi
    469 		
    470 if [ ${stat_maxbytes} -lt ${maxbytes} ]; then
    471 	stat_maxbytes=${maxbytes}
    472 fi
    473 		
    474 if [ ${stat_minblocks} -gt ${minblocks} ]; then
    475 	stat_minblocks=${minblocks}
    476 fi
    477 		
    478 if [ ${stat_maxblocks} -lt ${maxblocks} ]; then
    479 	stat_maxblocks=${maxblocks}
    480 fi
    481 		
    482 stat_bytes=`expr ${stat_bytes} + ${lbytes}`
    483 stat_blocks=`expr ${stat_blocks} + ${lblocks}`
    484 stat_runs=`expr ${stat_runs} + ${lruns}`
    485 }
    486 
    487 stat_print()
    488 {
    489 if [ ${stat_runs} -gt 0 ]; then
    490 	stat_avgbytes=`expr "${stat_bytes}" / "${stat_runs}"`
    491 	stat_avgblocks=`expr "${stat_blocks}" / "${stat_runs}"`
    492 	
    493 	echo
    494 	echo "$1 statistics:"
    495 	echo "Leaked bytes: ${stat_minbytes} min, ${stat_avgbytes} avg, ${stat_maxbytes} max"
    496 	echo "Leaked blocks: ${stat_minblocks} min, ${stat_avgblocks} avg, ${stat_maxblocks} max"
    497 	echo "Total runs: ${stat_runs}"
    498 	echo
    499 fi
    500 }
    501 
    502 ########################## run_ciphers_server ##########################
    503 # local shell function to test server part of code (selfserv)
    504 ########################################################################
    505 run_ciphers_server()
    506 {
    507 html_head "Memory leak checking - server"
    508 
    509 stat_clear
    510 
    511 client_mode="NORMAL"	
    512 for server_mode in ${MODE_LIST}; do
    513 	set_test_mode
    514 	
    515 	for freebl in ${FREEBL_LIST}; do
    516 		set_freebl || continue
    517 		
    518 		LOGNAME=server-${BIT_NAME}-${freebl}-${server_mode}
    519 		LOGFILE=${LOGDIR}/${LOGNAME}.log
    520 		echo "Running ${LOGNAME}"
    521 		
    522 		(
    523 		    run_selfserv_dbg 2>> ${LOGFILE} &
    524 		    sleep 5
    525 		    run_strsclnt
    526 		)
    527 		
    528 		sleep 20
    529 		clear_freebl
    530 		
    531 		log_parse
    532 		ret=$?
    533 		
    534 		html_msg ${ret} 0 "${LOGNAME}" "produced a returncode of $ret, expected is 0"
    535 	done
    536 done
    537 
    538 stat_print "Selfserv"
    539 
    540 html "</TABLE><BR>"
    541 }
    542 
    543 ########################## run_ciphers_client ##########################
    544 # local shell function to test client part of code (strsclnt)
    545 ########################################################################
    546 run_ciphers_client()
    547 {
    548 html_head "Memory leak checking - client"
    549 
    550 stat_clear
    551 
    552 server_mode="NORMAL"
    553 for client_mode in ${MODE_LIST}; do
    554 	set_test_mode
    555 	
    556 	for freebl in ${FREEBL_LIST}; do
    557 		set_freebl || continue
    558 		
    559 		LOGNAME=client-${BIT_NAME}-${freebl}-${client_mode}
    560 		LOGFILE=${LOGDIR}/${LOGNAME}.log
    561 		echo "Running ${LOGNAME}"
    562 		
    563 		(
    564 		    run_selfserv &
    565 		    sleep 5
    566 		    run_strsclnt_dbg 2>> ${LOGFILE}
    567 		)
    568 		
    569 		sleep 20
    570 		clear_freebl
    571 		
    572 		log_parse
    573 		ret=$?
    574 		html_msg ${ret} 0 "${LOGNAME}" "produced a returncode of $ret, expected is 0"
    575 	done
    576 done
    577 
    578 stat_print "Strsclnt"
    579 
    580 html "</TABLE><BR>"
    581 }
    582 
    583 ########################## parse_logfile_dbx ###########################
    584 # local shell function to parse and process logs from dbx
    585 ########################################################################
    586 parse_logfile_dbx()
    587 {
    588 ${AWK} '
    589 BEGIN {
    590 	in_mel = 0
    591 	mel_line = 0
    592 	bytes = 0
    593 	lbytes = 0
    594 	minbytes = 9999999
    595 	maxbytes = 0
    596 	blocks = 0
    597 	lblocks = 0
    598 	minblocks = 9999999
    599 	maxblocks = 0
    600 	runs = 0
    601 	stack_string = ""
    602 	bin_name = ""
    603 }
    604 /Memory Leak \(mel\):/ ||
    605 /Possible memory leak -- address in block \(aib\):/ ||
    606 /Block in use \(biu\):/ {
    607 	in_mel = 1
    608 	stack_string = ""
    609 	next
    610 }
    611 in_mel == 1 && /^$/ {
    612 	print bin_name stack_string
    613 	in_mel = 0
    614 	mel_line = 0
    615 	next
    616 }
    617 in_mel == 1 {
    618 	mel_line += 1
    619 }
    620 /Found leaked block of size/ {
    621 	bytes += $6
    622 	blocks += 1
    623 	next
    624 }
    625 /Found .* leaked blocks/ {
    626 	bytes += $8
    627 	blocks += $2
    628 	next
    629 }
    630 /Found block of size/ {
    631 	bytes += $5
    632 	blocks += 1
    633 	next
    634 }
    635 /Found .* blocks totaling/ {
    636 	bytes += $5
    637 	blocks += $2
    638 	next
    639 }
    640 mel_line > 2 {
    641 	gsub(/\(\)/, "")
    642 	new_line = $2
    643 	stack_string = "/" new_line stack_string
    644 	next
    645 }
    646 /^Running: / {
    647 	bin_name = $2
    648 	next
    649 }
    650 /execution completed/ {
    651 	runs += 1
    652 	lbytes += bytes
    653 	minbytes = (minbytes < bytes) ? minbytes : bytes
    654 	maxbytes = (maxbytes > bytes) ? maxbytes : bytes
    655 	bytes = 0
    656 	lblocks += blocks
    657 	minblocks = (minblocks < blocks) ? minblocks : blocks
    658 	maxblocks = (maxblocks > blocks) ? maxblocks : blocks
    659 	blocks = 0
    660 	next
    661 }
    662 END {
    663 	print "# " lbytes " bytes " lblocks " blocks in " runs " runs " \
    664 	minbytes " minbytes " maxbytes " maxbytes " minblocks " minblocks " \
    665 	maxblocks " maxblocks " > "/dev/stderr"
    666 }' 2> ${TMP_COUNT}
    667 
    668 stat_add
    669 }
    670 
    671 ######################## parse_logfile_valgrind ########################
    672 # local shell function to parse and process logs from valgrind
    673 ########################################################################
    674 parse_logfile_valgrind()
    675 {
    676 ${AWK} '
    677 BEGIN {
    678 	in_mel = 0
    679 	in_sum = 0
    680 	bytes = 0
    681 	lbytes = 0
    682 	minbytes = 9999999
    683 	maxbytes = 0
    684 	blocks = 0
    685 	lblocks = 0
    686 	minblocks = 9999999
    687 	maxblocks = 0
    688 	runs = 0
    689 	stack_string = ""
    690 	bin_name = "" 
    691 }
    692 !/==[0-9]*==/ { 
    693 	if ( $1 == "Running:" ) 
    694 		bin_name = $2
    695 		bin_nf = split(bin_name, bin_fields, "/")
    696 		bin_name = bin_fields[bin_nf]
    697 	next
    698 }
    699 /blocks are/ {
    700 	in_mel = 1
    701 	stack_string = ""
    702 	next
    703 }
    704 /LEAK SUMMARY/ {
    705 	in_sum = 1
    706 	next
    707 }
    708 /^==[0-9]*== *$/ { 
    709 	if (in_mel)
    710 		print bin_name stack_string
    711 	if (in_sum) {
    712 		runs += 1
    713 		lbytes += bytes
    714 		minbytes = (minbytes < bytes) ? minbytes : bytes
    715 		maxbytes = (maxbytes > bytes) ? maxbytes : bytes
    716 		bytes = 0
    717 		lblocks += blocks
    718 		minblocks = (minblocks < blocks) ? minblocks : blocks
    719 		maxblocks = (maxblocks > blocks) ? maxblocks : blocks
    720 		blocks = 0
    721 	}
    722 	in_sum = 0
    723 	in_mel = 0
    724 	next
    725 }
    726 in_mel == 1 {	
    727 	new_line = $4
    728 	if ( new_line == "(within")
    729 		new_line = "*"
    730 	stack_string = "/" new_line stack_string
    731 }
    732 in_sum == 1 {
    733 	for (i = 2; i <= NF; i++) {
    734 		if ($i == "bytes") {
    735 			str = $(i - 1)
    736 			gsub(",", "", str)
    737 			bytes += str
    738 		}
    739 		if ($i == "blocks.") {
    740 			str = $(i - 1)
    741 			gsub(",", "", str)
    742 			blocks += str
    743 		}
    744 	}
    745 }
    746 END {
    747 	print "# " lbytes " bytes " lblocks " blocks in " runs " runs " \
    748 	minbytes " minbytes " maxbytes " maxbytes " minblocks " minblocks " \
    749 	maxblocks " maxblocks " > "/dev/stderr"
    750 }' 2> ${TMP_COUNT}
    751 
    752 stat_add
    753 }
    754 
    755 ############################# check_ignored ############################
    756 # local shell function to check all stacks if they are not ignored
    757 ########################################################################
    758 check_ignored()
    759 {
    760 ${AWK} -F/ '
    761 BEGIN {
    762 	ignore = "'${IGNORED_STACKS}'"
    763 	# read in the ignore file
    764 	BUGNUM = ""
    765 	count = 0
    766 	new = 0
    767 	while ((getline line < ignore) > 0)  {
    768 		if (line ~ "^#[0-9]+") {
    769 			BUGNUM = line
    770 		} else if (line ~ "^#") {
    771 			continue
    772 		} else if (line == "") {
    773 			continue
    774 		} else {
    775 			bugnum_array[count] = BUGNUM
    776 			# Create a regular expression for the ignored stack:
    777 			# replace * with % so we can later replace them with regular expressions
    778 			# without messing up everything (the regular expressions contain *)
    779 			gsub("\\*", "%", line)
    780 			# replace %% with .*
    781 			gsub("%%", ".*", line)
    782 			# replace % with [^/]*
    783 			gsub("%", "[^/]*", line)
    784 			# add ^ at the beginning
    785 			# add $ at the end
    786 			line_array[count] = "^" line "$"
    787 			count++
    788 		}
    789 	}
    790 }
    791 {
    792 	match_found = 0
    793 	# Look for matching ignored stack
    794 	for (i = 0; i < count; i++) {
    795 		if ($0 ~ line_array[i]) {
    796 			# found a match
    797 			match_found = 1
    798 			bug_found = bugnum_array[i]
    799 			break
    800 		}
    801 	}
    802 	# Process result
    803 	if (match_found == 1 ) {
    804 			if (bug_found != "") {
    805 				print "IGNORED STACK (" bug_found "): " $0
    806 			} else {
    807 				print "IGNORED STACK: " $0
    808 			}
    809 	} else {
    810 			print "NEW STACK: " $0
    811 			new = 1
    812 	}
    813 }
    814 END {
    815 	exit new
    816 }'
    817 ret=$?
    818 return $ret
    819 }
    820 
    821 ############################### parse_log ##############################
    822 # local shell function to parse log file
    823 ########################################################################
    824 log_parse()
    825 {
    826 ${PARSE_LOGFILE} < ${LOGFILE} > ${TMP_STACKS}
    827 echo "${SCRIPTNAME}: Processing log ${LOGNAME}:" > ${TMP_SORTED}
    828 cat ${TMP_STACKS} | sort -u | check_ignored >> ${TMP_SORTED}
    829 ret=$?
    830 echo >> ${TMP_SORTED}
    831 
    832 cat ${TMP_SORTED} | tee -a ${FOUNDLEAKS}
    833 rm ${TMP_STACKS} ${TMP_SORTED}
    834 
    835 return ${ret}
    836 }
    837 
    838 ############################## cnt_total ###############################
    839 # local shell function to count total leaked bytes
    840 ########################################################################
    841 cnt_total()
    842 {
    843 echo ""
    844 echo "TinderboxPrint:${OPT} Lk bytes: ${tbytes}"
    845 echo "TinderboxPrint:${OPT} Lk blocks: ${tblocks}"
    846 echo "TinderboxPrint:${OPT} # of runs: ${truns}"
    847 echo ""
    848 }
    849 
    850 ############################### run_ocsp ###############################
    851 # local shell function to run ocsp tests
    852 ########################################################################
    853 run_ocsp()
    854 {
    855 stat_clear
    856 
    857 cd ${QADIR}/iopr
    858 . ./ocsp_iopr.sh
    859 ocsp_iopr_run
    860 
    861 stat_print "Ocspclnt"
    862 }
    863 
    864 ############################## run_chains ##############################
    865 # local shell function to run PKIX certificate chains tests
    866 ########################################################################
    867 run_chains()
    868 {
    869    stat_clear
    870 
    871    LOGNAME="chains"
    872    LOGFILE=${LOGDIR}/chains.log
    873 
    874    . ${QADIR}/chains/chains.sh
    875 
    876    stat_print "Chains"
    877 }
    878 
    879 ############################## run_chains ##############################
    880 # local shell function to run memory leak tests
    881 #
    882 # NSS_MEMLEAK_TESTS - list of tests to run, if not defined before,
    883 # then is redefined to default list 
    884 ########################################################################
    885 memleak_run_tests()
    886 {
    887    nss_memleak_tests="ssl_server ssl_client chains ocsp"
    888    NSS_MEMLEAK_TESTS="${NSS_MEMLEAK_TESTS:-$nss_memleak_tests}"
    889 
    890    for MEMLEAK_TEST in ${NSS_MEMLEAK_TESTS}
    891    do
    892        case "${MEMLEAK_TEST}" in
    893        "ssl_server")
    894            run_ciphers_server
    895            ;;
    896        "ssl_client")
    897            run_ciphers_client
    898            ;;
    899        "chains")
    900            run_chains
    901            ;;
    902        "ocsp")
    903            run_ocsp
    904            ;;
    905        esac
    906    done
    907 }
    908 
    909 ################################# main #################################
    910 
    911 memleak_init
    912 memleak_run_tests
    913 cnt_total
    914 memleak_cleanup