summaryrefslogtreecommitdiffstats
path: root/security/nss/tests/memleak/memleak.sh
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/tests/memleak/memleak.sh')
-rwxr-xr-xsecurity/nss/tests/memleak/memleak.sh915
1 files changed, 915 insertions, 0 deletions
diff --git a/security/nss/tests/memleak/memleak.sh b/security/nss/tests/memleak/memleak.sh
new file mode 100755
index 000000000..45e432bee
--- /dev/null
+++ b/security/nss/tests/memleak/memleak.sh
@@ -0,0 +1,915 @@
+#!/bin/bash
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+########################################################################
+#
+# mozilla/security/nss/tests/memleak/memleak.sh
+#
+# Script to test memory leaks in NSS
+#
+# needs to work on Solaris and Linux platforms, on others just print a message
+# that OS is not supported
+#
+# special strings
+# ---------------
+# FIXME ... known problems, search for this string
+# NOTE .... unexpected behavior
+#
+########################################################################
+
+############################# memleak_init #############################
+# local shell function to initialize this script
+########################################################################
+memleak_init()
+{
+ if [ -z "${INIT_SOURCED}" -o "${INIT_SOURCED}" != "TRUE" ]; then
+ cd ../common
+ . ./init.sh
+ fi
+
+ if [ ! -r ${CERT_LOG_FILE} ]; then
+ cd ${QADIR}/cert
+ . ./cert.sh
+ fi
+
+ SCRIPTNAME="memleak.sh"
+ if [ -z "${CLEANUP}" ] ; then
+ CLEANUP="${SCRIPTNAME}"
+ fi
+
+ OLD_LIBRARY_PATH=${LD_LIBRARY_PATH}
+ TMP_LIBDIR="${HOSTDIR}/tmp"
+ TMP_STACKS="${HOSTDIR}/stacks"
+ TMP_SORTED="${HOSTDIR}/sorted"
+ TMP_COUNT="${HOSTDIR}/count"
+ DBXOUT="${HOSTDIR}/dbxout"
+ DBXERR="${HOSTDIR}/dbxerr"
+ DBXCMD="${HOSTDIR}/dbxcmd"
+
+ PORT=${PORT:-8443}
+
+ MODE_LIST="NORMAL BYPASS FIPS"
+
+ SERVER_DB="${HOSTDIR}/server_memleak"
+ CLIENT_DB="${HOSTDIR}/client_memleak"
+ cp -r ${HOSTDIR}/server ${SERVER_DB}
+ cp -r ${HOSTDIR}/client ${CLIENT_DB}
+
+ LOGDIR="${HOSTDIR}/memleak_logs"
+ mkdir -p ${LOGDIR}
+
+ FOUNDLEAKS="${LOGDIR}/foundleaks"
+
+ REQUEST_FILE="${QADIR}/memleak/sslreq.dat"
+ IGNORED_STACKS="${QADIR}/memleak/ignored"
+
+ gline=`echo ${OBJDIR} | grep "_64_"`
+ if [ -n "${gline}" ] ; then
+ BIT_NAME="64"
+ else
+ BIT_NAME="32"
+ fi
+
+ case "${OS_NAME}" in
+ "SunOS")
+ DBX=`which dbx`
+ AWK=nawk
+
+ if [ $? -eq 0 ] ; then
+ echo "${SCRIPTNAME}: DBX found: ${DBX}"
+ else
+ echo "${SCRIPTNAME}: DBX not found, skipping memory leak checking."
+ exit 0
+ fi
+
+ PROC_ARCH=`uname -p`
+
+ if [ "${PROC_ARCH}" = "sparc" ] ; then
+ if [ "${BIT_NAME}" = "64" ] ; then
+ FREEBL_DEFAULT="libfreebl_64fpu_3"
+ FREEBL_LIST="${FREEBL_DEFAULT} libfreebl_64int_3"
+ else
+ FREEBL_DEFAULT="libfreebl_32fpu_3"
+ FREEBL_LIST="${FREEBL_DEFAULT} libfreebl_32int64_3"
+ fi
+ else
+ if [ "${BIT_NAME}" = "64" ] ; then
+ echo "${SCRIPTNAME}: OS not supported for memory leak checking."
+ exit 0
+ fi
+
+ FREEBL_DEFAULT="libfreebl_3"
+ FREEBL_LIST="${FREEBL_DEFAULT}"
+ fi
+
+ RUN_COMMAND_DBG="run_command_dbx"
+ PARSE_LOGFILE="parse_logfile_dbx"
+ ;;
+ "Linux")
+ VALGRIND=`which valgrind`
+ AWK=awk
+
+ if [ $? -eq 0 ] ; then
+ echo "${SCRIPTNAME}: Valgrind found: ${VALGRIND}"
+ else
+ echo "${SCRIPTNAME}: Valgrind not found, skipping memory leak checking."
+ exit 0
+ fi
+
+ FREEBL_DEFAULT="libfreebl_3"
+ FREEBL_LIST="${FREEBL_DEFAULT}"
+
+ RUN_COMMAND_DBG="run_command_valgrind"
+ PARSE_LOGFILE="parse_logfile_valgrind"
+ ;;
+ *)
+ echo "${SCRIPTNAME}: OS not supported for memory leak checking."
+ exit 0
+ ;;
+ esac
+
+ if [ "${BUILD_OPT}" = "1" ] ; then
+ OPT="OPT"
+ else
+ OPT="DBG"
+ fi
+
+ NSS_DISABLE_UNLOAD="1"
+ export NSS_DISABLE_UNLOAD
+
+ 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"
+ TSTCLNT_ATTR="-p ${PORT} -h ${HOSTADDR} -c j -f -d ${CLIENT_DB} -w nss -o"
+ STRSCLNT_ATTR="-q -p ${PORT} -d ${CLIENT_DB} -w nss -c 1000 -n TestUser ${HOSTADDR}"
+
+ tbytes=0
+ tblocks=0
+ truns=0
+
+ MEMLEAK_DBG=1
+ export MEMLEAK_DBG
+}
+
+########################### memleak_cleanup ############################
+# local shell function to clean up after this script
+########################################################################
+memleak_cleanup()
+{
+ unset MEMLEAK_DBG
+ unset NSS_DISABLE_UNLOAD
+
+ . ${QADIR}/common/cleanup.sh
+}
+
+############################ set_test_mode #############################
+# local shell function to set testing mode for server and for client
+########################################################################
+set_test_mode()
+{
+ if [ "${server_mode}" = "BYPASS" ] ; then
+ echo "${SCRIPTNAME}: BYPASS is ON"
+ SERVER_OPTION="-B -s"
+ CLIENT_OPTION=""
+ elif [ "${client_mode}" = "BYPASS" ] ; then
+ echo "${SCRIPTNAME}: BYPASS is ON"
+ SERVER_OPTION=""
+ CLIENT_OPTION="-B -s"
+ else
+ echo "${SCRIPTNAME}: BYPASS is OFF"
+ SERVER_OPTION=""
+ CLIENT_OPTION=""
+ fi
+
+ if [ "${server_mode}" = "FIPS" ] ; then
+ ${BINDIR}/modutil -dbdir ${SERVER_DB} -fips true -force
+ ${BINDIR}/modutil -dbdir ${SERVER_DB} -list
+ ${BINDIR}/modutil -dbdir ${CLIENT_DB} -fips false -force
+ ${BINDIR}/modutil -dbdir ${CLIENT_DB} -list
+
+ echo "${SCRIPTNAME}: FIPS is ON"
+ cipher_list="c d e i j k n v y z"
+ elif [ "${client_mode}" = "FIPS" ] ; then
+
+ ${BINDIR}/modutil -dbdir ${SERVER_DB} -fips false -force
+ ${BINDIR}/modutil -dbdir ${SERVER_DB} -list
+ ${BINDIR}/modutil -dbdir ${CLIENT_DB} -fips true -force
+ ${BINDIR}/modutil -dbdir ${CLIENT_DB} -list
+
+ echo "${SCRIPTNAME}: FIPS is ON"
+ cipher_list="c d e i j k n v y z"
+ else
+ ${BINDIR}/modutil -dbdir ${SERVER_DB} -fips false -force
+ ${BINDIR}/modutil -dbdir ${SERVER_DB} -list
+ ${BINDIR}/modutil -dbdir ${CLIENT_DB} -fips false -force
+ ${BINDIR}/modutil -dbdir ${CLIENT_DB} -list
+
+ echo "${SCRIPTNAME}: FIPS is OFF"
+ # ciphers l and m removed, see bug 1136095
+ 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"
+ fi
+}
+
+############################## set_freebl ##############################
+# local shell function to set freebl - sets temporary path for libraries
+########################################################################
+set_freebl()
+{
+ if [ "${freebl}" = "${FREEBL_DEFAULT}" ] ; then
+ LD_LIBRARY_PATH="${OLD_LIBRARY_PATH}"
+ export LD_LIBRARY_PATH
+ else
+ if [ -d "${TMP_LIBDIR}" ] ; then
+ rm -rf ${TMP_LIBDIR}
+ fi
+
+ mkdir ${TMP_LIBDIR}
+ [ $? -ne 0 ] && html_failed "Create temp directory" && return 1
+
+ cp ${DIST}/${OBJDIR}/lib/*.so ${DIST}/${OBJDIR}/lib/*.chk ${TMP_LIBDIR}
+ [ $? -ne 0 ] && html_failed "Copy libraries to temp directory" && return 1
+
+ echo "${SCRIPTNAME}: Using ${freebl} instead of ${FREEBL_DEFAULT}"
+
+ mv ${TMP_LIBDIR}/${FREEBL_DEFAULT}.so ${TMP_LIBDIR}/${FREEBL_DEFAULT}.so.orig
+ [ $? -ne 0 ] && html_failed "Move ${FREEBL_DEFAULT}.so -> ${FREEBL_DEFAULT}.so.orig" && return 1
+
+ cp ${TMP_LIBDIR}/${freebl}.so ${TMP_LIBDIR}/${FREEBL_DEFAULT}.so
+ [ $? -ne 0 ] && html_failed "Copy ${freebl}.so -> ${FREEBL_DEFAULT}.so" && return 1
+
+ mv ${TMP_LIBDIR}/${FREEBL_DEFAULT}.chk ${TMP_LIBDIR}/${FREEBL_DEFAULT}.chk.orig
+ [ $? -ne 0 ] && html_failed "Move ${FREEBL_DEFAULT}.chk -> ${FREEBL_DEFAULT}.chk.orig" && return 1
+
+ cp ${TMP_LIBDIR}/${freebl}.chk ${TMP_LIBDIR}/${FREEBL_DEFAULT}.chk
+ [ $? -ne 0 ] && html_failed "Copy ${freebl}.chk to temp directory" && return 1
+
+ echo "ls -l ${TMP_LIBDIR}"
+ ls -l ${TMP_LIBDIR}
+
+ LD_LIBRARY_PATH="${TMP_LIBDIR}"
+ export LD_LIBRARY_PATH
+ fi
+
+ return 0
+}
+
+############################# clear_freebl #############################
+# local shell function to set default library path and clear temporary
+# directory for libraries created by function set_freebl
+########################################################################
+clear_freebl()
+{
+ LD_LIBRARY_PATH="${OLD_LIBRARY_PATH}"
+ export LD_LIBRARY_PATH
+
+ if [ -d "${TMP_LIBDIR}" ] ; then
+ rm -rf ${TMP_LIBDIR}
+ fi
+}
+
+############################ run_command_dbx ###########################
+# local shell function to run command under dbx tool
+########################################################################
+run_command_dbx()
+{
+ COMMAND=$1
+ shift
+ ATTR=$*
+
+ COMMAND=`which ${COMMAND}`
+
+ echo "dbxenv follow_fork_mode parent" > ${DBXCMD}
+ echo "dbxenv rtc_mel_at_exit verbose" >> ${DBXCMD}
+ echo "dbxenv rtc_biu_at_exit verbose" >> ${DBXCMD}
+ echo "check -memuse -match 16 -frames 16" >> ${DBXCMD}
+ echo "run ${ATTR}" >> ${DBXCMD}
+
+ export NSS_DISABLE_ARENA_FREE_LIST=1
+
+ echo "${SCRIPTNAME}: -------- Running ${COMMAND} under DBX:"
+ echo "${DBX} ${COMMAND}"
+ echo "${SCRIPTNAME}: -------- DBX commands:"
+ cat ${DBXCMD}
+
+ ( ${DBX} ${COMMAND} < ${DBXCMD} > ${DBXOUT} 2> ${DBXERR} )
+ grep -v Reading ${DBXOUT} 1>&2
+ cat ${DBXERR}
+
+ unset NSS_DISABLE_ARENA_FREE_LIST
+
+ grep "exit code is" ${DBXOUT}
+ grep "exit code is 0" ${DBXOUT} > /dev/null
+ return $?
+}
+
+######################### run_command_valgrind #########################
+# local shell function to run command under valgrind tool
+########################################################################
+run_command_valgrind()
+{
+ COMMAND=$1
+ shift
+ ATTR=$*
+
+ export NSS_DISABLE_ARENA_FREE_LIST=1
+
+ echo "${SCRIPTNAME}: -------- Running ${COMMAND} under Valgrind:"
+ echo "${VALGRIND} --tool=memcheck --leak-check=yes --show-reachable=yes --partial-loads-ok=yes --leak-resolution=high --num-callers=50 ${COMMAND} ${ATTR}"
+ echo "Running: ${COMMAND} ${ATTR}" 1>&2
+ ${VALGRIND} --tool=memcheck --leak-check=yes --show-reachable=yes --partial-loads-ok=yes --leak-resolution=high --num-callers=50 ${COMMAND} ${ATTR} 1>&2
+ ret=$?
+ echo "==0=="
+
+ unset NSS_DISABLE_ARENA_FREE_LIST
+
+ return $ret
+}
+
+############################# run_selfserv #############################
+# local shell function to start selfserv
+########################################################################
+run_selfserv()
+{
+ echo "PATH=${PATH}"
+ echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}"
+ echo "${SCRIPTNAME}: -------- Running selfserv:"
+ echo "selfserv ${SELFSERV_ATTR}"
+ ${BINDIR}/selfserv ${SELFSERV_ATTR}
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ html_failed "${LOGNAME}: Selfserv"
+ echo "${SCRIPTNAME} ${LOGNAME}: " \
+ "Selfserv produced a returncode of ${ret} - FAILED"
+ fi
+}
+
+########################### run_selfserv_dbg ###########################
+# local shell function to start selfserv under debug tool
+########################################################################
+run_selfserv_dbg()
+{
+ echo "PATH=${PATH}"
+ echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}"
+ ${RUN_COMMAND_DBG} ${BINDIR}/selfserv ${SERVER_OPTION} ${SELFSERV_ATTR}
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ html_failed "${LOGNAME}: Selfserv"
+ echo "${SCRIPTNAME} ${LOGNAME}: " \
+ "Selfserv produced a returncode of ${ret} - FAILED"
+ fi
+}
+
+############################# run_strsclnt #############################
+# local shell function to run strsclnt for all ciphers and send stop
+# command to selfserv over tstclnt
+########################################################################
+run_strsclnt()
+{
+ for cipher in ${cipher_list}; do
+ VMIN="ssl3"
+ VMAX="tls1.2"
+ case "${cipher}" in
+ f|g)
+ # TLS 1.1 disallows export cipher suites.
+ VMAX="tls1.0"
+ ;;
+ esac
+ ATTR="${STRSCLNT_ATTR} -C ${cipher} -V ${VMIN}:${VMAX}"
+ echo "${SCRIPTNAME}: -------- Trying cipher ${cipher}:"
+ echo "strsclnt ${ATTR}"
+ ${BINDIR}/strsclnt ${ATTR}
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ html_failed "${LOGNAME}: Strsclnt with cipher ${cipher}"
+ echo "${SCRIPTNAME} ${LOGNAME}: " \
+ "Strsclnt produced a returncode of ${ret} - FAILED"
+ fi
+ done
+
+ ATTR="${TSTCLNT_ATTR} -V ssl3:tls1.2"
+ echo "${SCRIPTNAME}: -------- Stopping server:"
+ echo "tstclnt ${ATTR} < ${REQUEST_FILE}"
+ ${BINDIR}/tstclnt ${ATTR} < ${REQUEST_FILE}
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ html_failed "${LOGNAME}: Tstclnt"
+ echo "${SCRIPTNAME} ${LOGNAME}: " \
+ "Tstclnt produced a returncode of ${ret} - FAILED"
+ fi
+
+ sleep 20
+ kill $(jobs -p) 2> /dev/null
+}
+
+########################### run_strsclnt_dbg ###########################
+# local shell function to run strsclnt under debug tool for all ciphers
+# and send stop command to selfserv over tstclnt
+########################################################################
+run_strsclnt_dbg()
+{
+ for cipher in ${cipher_list}; do
+ VMIN="ssl3"
+ VMAX="tls1.2"
+ case "${cipher}" in
+ f|g)
+ # TLS 1.1 disallows export cipher suites.
+ VMAX="tls1.0"
+ ;;
+ esac
+ ATTR="${STRSCLNT_ATTR} -C ${cipher} -V ${VMIN}:${VMAX}"
+ ${RUN_COMMAND_DBG} ${BINDIR}/strsclnt ${CLIENT_OPTION} ${ATTR}
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ html_failed "${LOGNAME}: Strsclnt with cipher ${cipher}"
+ echo "${SCRIPTNAME} ${LOGNAME}: " \
+ "Strsclnt produced a returncode of ${ret} - FAILED"
+ fi
+ done
+
+ ATTR="${TSTCLNT_ATTR} -V ssl3:tls1.2"
+ echo "${SCRIPTNAME}: -------- Stopping server:"
+ echo "tstclnt ${ATTR} < ${REQUEST_FILE}"
+ ${BINDIR}/tstclnt ${ATTR} < ${REQUEST_FILE}
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ html_failed "${LOGNAME}: Tstclnt"
+ echo "${SCRIPTNAME} ${LOGNAME}: " \
+ "Tstclnt produced a returncode of ${ret} - FAILED"
+ fi
+
+ kill $(jobs -p) 2> /dev/null
+}
+
+stat_clear()
+{
+ stat_minbytes=9999999
+ stat_maxbytes=0
+ stat_minblocks=9999999
+ stat_maxblocks=0
+ stat_bytes=0
+ stat_blocks=0
+ stat_runs=0
+}
+
+stat_add()
+{
+ read hash lbytes bytes_str lblocks blocks_str in_str lruns runs_str \
+ minbytes minbytes_str maxbytes maxbytes_str minblocks \
+ minblocks_str maxblocks maxblocks_str rest < ${TMP_COUNT}
+ rm ${TMP_COUNT}
+
+ tbytes=`expr ${tbytes} + ${lbytes}`
+ tblocks=`expr ${tblocks} + ${lblocks}`
+ truns=`expr ${truns} + ${lruns}`
+
+ if [ ${stat_minbytes} -gt ${minbytes} ]; then
+ stat_minbytes=${minbytes}
+ fi
+
+ if [ ${stat_maxbytes} -lt ${maxbytes} ]; then
+ stat_maxbytes=${maxbytes}
+ fi
+
+ if [ ${stat_minblocks} -gt ${minblocks} ]; then
+ stat_minblocks=${minblocks}
+ fi
+
+ if [ ${stat_maxblocks} -lt ${maxblocks} ]; then
+ stat_maxblocks=${maxblocks}
+ fi
+
+ stat_bytes=`expr ${stat_bytes} + ${lbytes}`
+ stat_blocks=`expr ${stat_blocks} + ${lblocks}`
+ stat_runs=`expr ${stat_runs} + ${lruns}`
+}
+
+stat_print()
+{
+ if [ ${stat_runs} -gt 0 ]; then
+ stat_avgbytes=`expr "${stat_bytes}" / "${stat_runs}"`
+ stat_avgblocks=`expr "${stat_blocks}" / "${stat_runs}"`
+
+ echo
+ echo "$1 statistics:"
+ echo "Leaked bytes: ${stat_minbytes} min, ${stat_avgbytes} avg, ${stat_maxbytes} max"
+ echo "Leaked blocks: ${stat_minblocks} min, ${stat_avgblocks} avg, ${stat_maxblocks} max"
+ echo "Total runs: ${stat_runs}"
+ echo
+ fi
+}
+
+########################## run_ciphers_server ##########################
+# local shell function to test server part of code (selfserv)
+########################################################################
+run_ciphers_server()
+{
+ html_head "Memory leak checking - server"
+
+ stat_clear
+
+ client_mode="NORMAL"
+ for server_mode in ${MODE_LIST}; do
+ set_test_mode
+
+ for freebl in ${FREEBL_LIST}; do
+ set_freebl || continue
+
+ LOGNAME=server-${BIT_NAME}-${freebl}-${server_mode}
+ LOGFILE=${LOGDIR}/${LOGNAME}.log
+ echo "Running ${LOGNAME}"
+
+ (
+ run_selfserv_dbg 2>> ${LOGFILE} &
+ sleep 5
+ run_strsclnt
+ )
+
+ sleep 20
+ clear_freebl
+
+ log_parse
+ ret=$?
+
+ html_msg ${ret} 0 "${LOGNAME}" "produced a returncode of $ret, expected is 0"
+ done
+ done
+
+ stat_print "Selfserv"
+
+ html "</TABLE><BR>"
+}
+
+########################## run_ciphers_client ##########################
+# local shell function to test client part of code (strsclnt)
+########################################################################
+run_ciphers_client()
+{
+ html_head "Memory leak checking - client"
+
+ stat_clear
+
+ server_mode="NORMAL"
+ for client_mode in ${MODE_LIST}; do
+ set_test_mode
+
+ for freebl in ${FREEBL_LIST}; do
+ set_freebl || continue
+
+ LOGNAME=client-${BIT_NAME}-${freebl}-${client_mode}
+ LOGFILE=${LOGDIR}/${LOGNAME}.log
+ echo "Running ${LOGNAME}"
+
+ (
+ run_selfserv &
+ sleep 5
+ run_strsclnt_dbg 2>> ${LOGFILE}
+ )
+
+ sleep 20
+ clear_freebl
+
+ log_parse
+ ret=$?
+ html_msg ${ret} 0 "${LOGNAME}" "produced a returncode of $ret, expected is 0"
+ done
+ done
+
+ stat_print "Strsclnt"
+
+ html "</TABLE><BR>"
+}
+
+########################## parse_logfile_dbx ###########################
+# local shell function to parse and process logs from dbx
+########################################################################
+parse_logfile_dbx()
+{
+ ${AWK} '
+ BEGIN {
+ in_mel = 0
+ mel_line = 0
+ bytes = 0
+ lbytes = 0
+ minbytes = 9999999
+ maxbytes = 0
+ blocks = 0
+ lblocks = 0
+ minblocks = 9999999
+ maxblocks = 0
+ runs = 0
+ stack_string = ""
+ bin_name = ""
+ }
+ /Memory Leak \(mel\):/ ||
+ /Possible memory leak -- address in block \(aib\):/ ||
+ /Block in use \(biu\):/ {
+ in_mel = 1
+ stack_string = ""
+ next
+ }
+ in_mel == 1 && /^$/ {
+ print bin_name stack_string
+ in_mel = 0
+ mel_line = 0
+ next
+ }
+ in_mel == 1 {
+ mel_line += 1
+ }
+ /Found leaked block of size/ {
+ bytes += $6
+ blocks += 1
+ next
+ }
+ /Found .* leaked blocks/ {
+ bytes += $8
+ blocks += $2
+ next
+ }
+ /Found block of size/ {
+ bytes += $5
+ blocks += 1
+ next
+ }
+ /Found .* blocks totaling/ {
+ bytes += $5
+ blocks += $2
+ next
+ }
+ mel_line > 2 {
+ gsub(/\(\)/, "")
+ new_line = $2
+ stack_string = "/" new_line stack_string
+ next
+ }
+ /^Running: / {
+ bin_name = $2
+ next
+ }
+ /execution completed/ {
+ runs += 1
+ lbytes += bytes
+ minbytes = (minbytes < bytes) ? minbytes : bytes
+ maxbytes = (maxbytes > bytes) ? maxbytes : bytes
+ bytes = 0
+ lblocks += blocks
+ minblocks = (minblocks < blocks) ? minblocks : blocks
+ maxblocks = (maxblocks > blocks) ? maxblocks : blocks
+ blocks = 0
+ next
+ }
+ END {
+ print "# " lbytes " bytes " lblocks " blocks in " runs " runs " \
+ minbytes " minbytes " maxbytes " maxbytes " minblocks " minblocks " \
+ maxblocks " maxblocks " > "/dev/stderr"
+ }' 2> ${TMP_COUNT}
+
+ stat_add
+}
+
+######################## parse_logfile_valgrind ########################
+# local shell function to parse and process logs from valgrind
+########################################################################
+parse_logfile_valgrind()
+{
+ ${AWK} '
+ BEGIN {
+ in_mel = 0
+ in_sum = 0
+ bytes = 0
+ lbytes = 0
+ minbytes = 9999999
+ maxbytes = 0
+ blocks = 0
+ lblocks = 0
+ minblocks = 9999999
+ maxblocks = 0
+ runs = 0
+ stack_string = ""
+ bin_name = ""
+ }
+ !/==[0-9]*==/ {
+ if ( $1 == "Running:" )
+ bin_name = $2
+ bin_nf = split(bin_name, bin_fields, "/")
+ bin_name = bin_fields[bin_nf]
+ next
+ }
+ /blocks are/ {
+ in_mel = 1
+ stack_string = ""
+ next
+ }
+ /LEAK SUMMARY/ {
+ in_sum = 1
+ next
+ }
+ /^==[0-9]*== *$/ {
+ if (in_mel)
+ print bin_name stack_string
+ if (in_sum) {
+ runs += 1
+ lbytes += bytes
+ minbytes = (minbytes < bytes) ? minbytes : bytes
+ maxbytes = (maxbytes > bytes) ? maxbytes : bytes
+ bytes = 0
+ lblocks += blocks
+ minblocks = (minblocks < blocks) ? minblocks : blocks
+ maxblocks = (maxblocks > blocks) ? maxblocks : blocks
+ blocks = 0
+ }
+ in_sum = 0
+ in_mel = 0
+ next
+ }
+ in_mel == 1 {
+ new_line = $4
+ if ( new_line == "(within")
+ new_line = "*"
+ stack_string = "/" new_line stack_string
+ }
+ in_sum == 1 {
+ for (i = 2; i <= NF; i++) {
+ if ($i == "bytes") {
+ str = $(i - 1)
+ gsub(",", "", str)
+ bytes += str
+ }
+ if ($i == "blocks.") {
+ str = $(i - 1)
+ gsub(",", "", str)
+ blocks += str
+ }
+ }
+ }
+ END {
+ print "# " lbytes " bytes " lblocks " blocks in " runs " runs " \
+ minbytes " minbytes " maxbytes " maxbytes " minblocks " minblocks " \
+ maxblocks " maxblocks " > "/dev/stderr"
+ }' 2> ${TMP_COUNT}
+
+ stat_add
+}
+
+############################# check_ignored ############################
+# local shell function to check all stacks if they are not ignored
+########################################################################
+check_ignored()
+{
+ ${AWK} -F/ '
+ BEGIN {
+ ignore = "'${IGNORED_STACKS}'"
+ # read in the ignore file
+ BUGNUM = ""
+ count = 0
+ new = 0
+ while ((getline line < ignore) > 0) {
+ if (line ~ "^#[0-9]+") {
+ BUGNUM = line
+ } else if (line ~ "^#") {
+ continue
+ } else if (line == "") {
+ continue
+ } else {
+ bugnum_array[count] = BUGNUM
+ # Create a regular expression for the ignored stack:
+ # replace * with % so we can later replace them with regular expressions
+ # without messing up everything (the regular expressions contain *)
+ gsub("\\*", "%", line)
+ # replace %% with .*
+ gsub("%%", ".*", line)
+ # replace % with [^/]*
+ gsub("%", "[^/]*", line)
+ # add ^ at the beginning
+ # add $ at the end
+ line_array[count] = "^" line "$"
+ count++
+ }
+ }
+ }
+ {
+ match_found = 0
+ # Look for matching ignored stack
+ for (i = 0; i < count; i++) {
+ if ($0 ~ line_array[i]) {
+ # found a match
+ match_found = 1
+ bug_found = bugnum_array[i]
+ break
+ }
+ }
+ # Process result
+ if (match_found == 1 ) {
+ if (bug_found != "") {
+ print "IGNORED STACK (" bug_found "): " $0
+ } else {
+ print "IGNORED STACK: " $0
+ }
+ } else {
+ print "NEW STACK: " $0
+ new = 1
+ }
+ }
+ END {
+ exit new
+ }'
+ ret=$?
+ return $ret
+}
+
+############################### parse_log ##############################
+# local shell function to parse log file
+########################################################################
+log_parse()
+{
+ ${PARSE_LOGFILE} < ${LOGFILE} > ${TMP_STACKS}
+ echo "${SCRIPTNAME}: Processing log ${LOGNAME}:" > ${TMP_SORTED}
+ cat ${TMP_STACKS} | sort -u | check_ignored >> ${TMP_SORTED}
+ ret=$?
+ echo >> ${TMP_SORTED}
+
+ cat ${TMP_SORTED} | tee -a ${FOUNDLEAKS}
+ rm ${TMP_STACKS} ${TMP_SORTED}
+
+ return ${ret}
+}
+
+############################## cnt_total ###############################
+# local shell function to count total leaked bytes
+########################################################################
+cnt_total()
+{
+ echo ""
+ echo "TinderboxPrint:${OPT} Lk bytes: ${tbytes}"
+ echo "TinderboxPrint:${OPT} Lk blocks: ${tblocks}"
+ echo "TinderboxPrint:${OPT} # of runs: ${truns}"
+ echo ""
+}
+
+############################### run_ocsp ###############################
+# local shell function to run ocsp tests
+########################################################################
+run_ocsp()
+{
+ stat_clear
+
+ cd ${QADIR}/iopr
+ . ./ocsp_iopr.sh
+ ocsp_iopr_run
+
+ stat_print "Ocspclnt"
+}
+
+############################## run_chains ##############################
+# local shell function to run PKIX certificate chains tests
+########################################################################
+run_chains()
+{
+ stat_clear
+
+ LOGNAME="chains"
+ LOGFILE=${LOGDIR}/chains.log
+
+ . ${QADIR}/chains/chains.sh
+
+ stat_print "Chains"
+}
+
+############################## run_chains ##############################
+# local shell function to run memory leak tests
+#
+# NSS_MEMLEAK_TESTS - list of tests to run, if not defined before,
+# then is redefined to default list
+########################################################################
+memleak_run_tests()
+{
+ nss_memleak_tests="ssl_server ssl_client chains ocsp"
+ NSS_MEMLEAK_TESTS="${NSS_MEMLEAK_TESTS:-$nss_memleak_tests}"
+
+ for MEMLEAK_TEST in ${NSS_MEMLEAK_TESTS}
+ do
+ case "${MEMLEAK_TEST}" in
+ "ssl_server")
+ run_ciphers_server
+ ;;
+ "ssl_client")
+ run_ciphers_client
+ ;;
+ "chains")
+ run_chains
+ ;;
+ "ocsp")
+ run_ocsp
+ ;;
+ esac
+ done
+}
+
+################################# main #################################
+
+memleak_init
+memleak_run_tests
+cnt_total
+memleak_cleanup
+