|
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 ABCDEF:C001:C002:C003:C004:C005:C006:C007:C008:C009:C00A:C00B:C00C:C00D:C00E:C00F:C010:C011:C012:C013:C014cdefgijklmnvyz -t 5" |
|
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 cipher_list="A B C D E F :C001 :C002 :C003 :C004 :C005 :C006 :C007 :C008 :C009 :C00A :C010 :C011 :C012 :C013 :C014 c d e f g i j k l m n v y z" |
|
210 fi |
|
211 } |
|
212 |
|
213 ############################## set_freebl ############################## |
|
214 # local shell function to set freebl - sets temporary path for libraries |
|
215 ######################################################################## |
|
216 set_freebl() |
|
217 { |
|
218 if [ "${freebl}" = "${FREEBL_DEFAULT}" ] ; then |
|
219 LD_LIBRARY_PATH="${OLD_LIBRARY_PATH}" |
|
220 export LD_LIBRARY_PATH |
|
221 else |
|
222 if [ -d "${TMP_LIBDIR}" ] ; then |
|
223 rm -rf ${TMP_LIBDIR} |
|
224 fi |
|
225 |
|
226 mkdir ${TMP_LIBDIR} |
|
227 [ $? -ne 0 ] && html_failed "Create temp directory" && return 1 |
|
228 |
|
229 cp ${DIST}/${OBJDIR}/lib/*.so ${DIST}/${OBJDIR}/lib/*.chk ${TMP_LIBDIR} |
|
230 [ $? -ne 0 ] && html_failed "Copy libraries to temp directory" && return 1 |
|
231 |
|
232 echo "${SCRIPTNAME}: Using ${freebl} instead of ${FREEBL_DEFAULT}" |
|
233 |
|
234 mv ${TMP_LIBDIR}/${FREEBL_DEFAULT}.so ${TMP_LIBDIR}/${FREEBL_DEFAULT}.so.orig |
|
235 [ $? -ne 0 ] && html_failed "Move ${FREEBL_DEFAULT}.so -> ${FREEBL_DEFAULT}.so.orig" && return 1 |
|
236 |
|
237 cp ${TMP_LIBDIR}/${freebl}.so ${TMP_LIBDIR}/${FREEBL_DEFAULT}.so |
|
238 [ $? -ne 0 ] && html_failed "Copy ${freebl}.so -> ${FREEBL_DEFAULT}.so" && return 1 |
|
239 |
|
240 mv ${TMP_LIBDIR}/${FREEBL_DEFAULT}.chk ${TMP_LIBDIR}/${FREEBL_DEFAULT}.chk.orig |
|
241 [ $? -ne 0 ] && html_failed "Move ${FREEBL_DEFAULT}.chk -> ${FREEBL_DEFAULT}.chk.orig" && return 1 |
|
242 |
|
243 cp ${TMP_LIBDIR}/${freebl}.chk ${TMP_LIBDIR}/${FREEBL_DEFAULT}.chk |
|
244 [ $? -ne 0 ] && html_failed "Copy ${freebl}.chk to temp directory" && return 1 |
|
245 |
|
246 echo "ls -l ${TMP_LIBDIR}" |
|
247 ls -l ${TMP_LIBDIR} |
|
248 |
|
249 LD_LIBRARY_PATH="${TMP_LIBDIR}" |
|
250 export LD_LIBRARY_PATH |
|
251 fi |
|
252 |
|
253 return 0 |
|
254 } |
|
255 |
|
256 ############################# clear_freebl ############################# |
|
257 # local shell function to set default library path and clear temporary |
|
258 # directory for libraries created by function set_freebl |
|
259 ######################################################################## |
|
260 clear_freebl() |
|
261 { |
|
262 LD_LIBRARY_PATH="${OLD_LIBRARY_PATH}" |
|
263 export LD_LIBRARY_PATH |
|
264 |
|
265 if [ -d "${TMP_LIBDIR}" ] ; then |
|
266 rm -rf ${TMP_LIBDIR} |
|
267 fi |
|
268 } |
|
269 |
|
270 ############################ run_command_dbx ########################### |
|
271 # local shell function to run command under dbx tool |
|
272 ######################################################################## |
|
273 run_command_dbx() |
|
274 { |
|
275 COMMAND=$1 |
|
276 shift |
|
277 ATTR=$* |
|
278 |
|
279 COMMAND=`which ${COMMAND}` |
|
280 |
|
281 echo "dbxenv follow_fork_mode parent" > ${DBXCMD} |
|
282 echo "dbxenv rtc_mel_at_exit verbose" >> ${DBXCMD} |
|
283 echo "dbxenv rtc_biu_at_exit verbose" >> ${DBXCMD} |
|
284 echo "check -memuse -match 16 -frames 16" >> ${DBXCMD} |
|
285 echo "run ${ATTR}" >> ${DBXCMD} |
|
286 |
|
287 export NSS_DISABLE_ARENA_FREE_LIST=1 |
|
288 |
|
289 echo "${SCRIPTNAME}: -------- Running ${COMMAND} under DBX:" |
|
290 echo "${DBX} ${COMMAND}" |
|
291 echo "${SCRIPTNAME}: -------- DBX commands:" |
|
292 cat ${DBXCMD} |
|
293 |
|
294 ( ${DBX} ${COMMAND} < ${DBXCMD} > ${DBXOUT} 2> ${DBXERR} ) |
|
295 grep -v Reading ${DBXOUT} 1>&2 |
|
296 cat ${DBXERR} |
|
297 |
|
298 unset NSS_DISABLE_ARENA_FREE_LIST |
|
299 |
|
300 grep "exit code is" ${DBXOUT} |
|
301 grep "exit code is 0" ${DBXOUT} > /dev/null |
|
302 return $? |
|
303 } |
|
304 |
|
305 ######################### run_command_valgrind ######################### |
|
306 # local shell function to run command under valgrind tool |
|
307 ######################################################################## |
|
308 run_command_valgrind() |
|
309 { |
|
310 COMMAND=$1 |
|
311 shift |
|
312 ATTR=$* |
|
313 |
|
314 export NSS_DISABLE_ARENA_FREE_LIST=1 |
|
315 |
|
316 echo "${SCRIPTNAME}: -------- Running ${COMMAND} under Valgrind:" |
|
317 echo "${VALGRIND} --tool=memcheck --leak-check=yes --show-reachable=yes --partial-loads-ok=yes --leak-resolution=high --num-callers=50 ${COMMAND} ${ATTR}" |
|
318 echo "Running: ${COMMAND} ${ATTR}" 1>&2 |
|
319 ${VALGRIND} --tool=memcheck --leak-check=yes --show-reachable=yes --partial-loads-ok=yes --leak-resolution=high --num-callers=50 ${COMMAND} ${ATTR} 1>&2 |
|
320 ret=$? |
|
321 echo "==0==" |
|
322 |
|
323 unset NSS_DISABLE_ARENA_FREE_LIST |
|
324 |
|
325 return $ret |
|
326 } |
|
327 |
|
328 ############################# run_selfserv ############################# |
|
329 # local shell function to start selfserv |
|
330 ######################################################################## |
|
331 run_selfserv() |
|
332 { |
|
333 echo "PATH=${PATH}" |
|
334 echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}" |
|
335 echo "${SCRIPTNAME}: -------- Running selfserv:" |
|
336 echo "selfserv ${SELFSERV_ATTR}" |
|
337 ${BINDIR}/selfserv ${SELFSERV_ATTR} |
|
338 ret=$? |
|
339 if [ $ret -ne 0 ]; then |
|
340 html_failed "${LOGNAME}: Selfserv" |
|
341 echo "${SCRIPTNAME} ${LOGNAME}: " \ |
|
342 "Selfserv produced a returncode of ${ret} - FAILED" |
|
343 fi |
|
344 } |
|
345 |
|
346 ########################### run_selfserv_dbg ########################### |
|
347 # local shell function to start selfserv under debug tool |
|
348 ######################################################################## |
|
349 run_selfserv_dbg() |
|
350 { |
|
351 echo "PATH=${PATH}" |
|
352 echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}" |
|
353 ${RUN_COMMAND_DBG} ${BINDIR}/selfserv ${SERVER_OPTION} ${SELFSERV_ATTR} |
|
354 ret=$? |
|
355 if [ $ret -ne 0 ]; then |
|
356 html_failed "${LOGNAME}: Selfserv" |
|
357 echo "${SCRIPTNAME} ${LOGNAME}: " \ |
|
358 "Selfserv produced a returncode of ${ret} - FAILED" |
|
359 fi |
|
360 } |
|
361 |
|
362 ############################# run_strsclnt ############################# |
|
363 # local shell function to run strsclnt for all ciphers and send stop |
|
364 # command to selfserv over tstclnt |
|
365 ######################################################################## |
|
366 run_strsclnt() |
|
367 { |
|
368 for cipher in ${cipher_list}; do |
|
369 VMIN="ssl3" |
|
370 VMAX= |
|
371 case "${cipher}" in |
|
372 A|B|C|D|E|F) |
|
373 # Enable SSL 2 only for SSL 2 cipher suites. |
|
374 VMIN="ssl2" |
|
375 ;; |
|
376 f|g) |
|
377 # TLS 1.1 disallows export cipher suites. |
|
378 VMAX="tls1.0" |
|
379 ;; |
|
380 esac |
|
381 ATTR="${STRSCLNT_ATTR} -C ${cipher} -V ${VMIN}:${VMAX}" |
|
382 echo "${SCRIPTNAME}: -------- Trying cipher ${cipher}:" |
|
383 echo "strsclnt ${ATTR}" |
|
384 ${BINDIR}/strsclnt ${ATTR} |
|
385 ret=$? |
|
386 if [ $ret -ne 0 ]; then |
|
387 html_failed "${LOGNAME}: Strsclnt with cipher ${cipher}" |
|
388 echo "${SCRIPTNAME} ${LOGNAME}: " \ |
|
389 "Strsclnt produced a returncode of ${ret} - FAILED" |
|
390 fi |
|
391 done |
|
392 |
|
393 echo "${SCRIPTNAME}: -------- Stopping server:" |
|
394 echo "tstclnt ${TSTCLNT_ATTR} < ${REQUEST_FILE}" |
|
395 ${BINDIR}/tstclnt ${TSTCLNT_ATTR} < ${REQUEST_FILE} |
|
396 ret=$? |
|
397 if [ $ret -ne 0 ]; then |
|
398 html_failed "${LOGNAME}: Tstclnt" |
|
399 echo "${SCRIPTNAME} ${LOGNAME}: " \ |
|
400 "Tstclnt produced a returncode of ${ret} - FAILED" |
|
401 fi |
|
402 |
|
403 sleep 20 |
|
404 kill $(jobs -p) 2> /dev/null |
|
405 } |
|
406 |
|
407 ########################### run_strsclnt_dbg ########################### |
|
408 # local shell function to run strsclnt under debug tool for all ciphers |
|
409 # and send stop command to selfserv over tstclnt |
|
410 ######################################################################## |
|
411 run_strsclnt_dbg() |
|
412 { |
|
413 for cipher in ${cipher_list}; do |
|
414 VMIN="ssl3" |
|
415 VMAX= |
|
416 case "${cipher}" in |
|
417 A|B|C|D|E|F) |
|
418 # Enable SSL 2 only for SSL 2 cipher suites. |
|
419 VMIN="ssl2" |
|
420 ;; |
|
421 f|g) |
|
422 # TLS 1.1 disallows export cipher suites. |
|
423 VMAX="tls1.0" |
|
424 ;; |
|
425 esac |
|
426 ATTR="${STRSCLNT_ATTR} -C ${cipher} -V ${VMIN}:${VMAX}" |
|
427 ${RUN_COMMAND_DBG} ${BINDIR}/strsclnt ${CLIENT_OPTION} ${ATTR} |
|
428 ret=$? |
|
429 if [ $ret -ne 0 ]; then |
|
430 html_failed "${LOGNAME}: Strsclnt with cipher ${cipher}" |
|
431 echo "${SCRIPTNAME} ${LOGNAME}: " \ |
|
432 "Strsclnt produced a returncode of ${ret} - FAILED" |
|
433 fi |
|
434 done |
|
435 |
|
436 echo "${SCRIPTNAME}: -------- Stopping server:" |
|
437 echo "tstclnt ${TSTCLNT_ATTR} < ${REQUEST_FILE}" |
|
438 ${BINDIR}/tstclnt ${TSTCLNT_ATTR} < ${REQUEST_FILE} |
|
439 ret=$? |
|
440 if [ $ret -ne 0 ]; then |
|
441 html_failed "${LOGNAME}: Tstclnt" |
|
442 echo "${SCRIPTNAME} ${LOGNAME}: " \ |
|
443 "Tstclnt produced a returncode of ${ret} - FAILED" |
|
444 fi |
|
445 |
|
446 kill $(jobs -p) 2> /dev/null |
|
447 } |
|
448 |
|
449 stat_clear() |
|
450 { |
|
451 stat_minbytes=9999999 |
|
452 stat_maxbytes=0 |
|
453 stat_minblocks=9999999 |
|
454 stat_maxblocks=0 |
|
455 stat_bytes=0 |
|
456 stat_blocks=0 |
|
457 stat_runs=0 |
|
458 } |
|
459 |
|
460 stat_add() |
|
461 { |
|
462 read hash lbytes bytes_str lblocks blocks_str in_str lruns runs_str \ |
|
463 minbytes minbytes_str maxbytes maxbytes_str minblocks \ |
|
464 minblocks_str maxblocks maxblocks_str rest < ${TMP_COUNT} |
|
465 rm ${TMP_COUNT} |
|
466 |
|
467 tbytes=`expr ${tbytes} + ${lbytes}` |
|
468 tblocks=`expr ${tblocks} + ${lblocks}` |
|
469 truns=`expr ${truns} + ${lruns}` |
|
470 |
|
471 if [ ${stat_minbytes} -gt ${minbytes} ]; then |
|
472 stat_minbytes=${minbytes} |
|
473 fi |
|
474 |
|
475 if [ ${stat_maxbytes} -lt ${maxbytes} ]; then |
|
476 stat_maxbytes=${maxbytes} |
|
477 fi |
|
478 |
|
479 if [ ${stat_minblocks} -gt ${minblocks} ]; then |
|
480 stat_minblocks=${minblocks} |
|
481 fi |
|
482 |
|
483 if [ ${stat_maxblocks} -lt ${maxblocks} ]; then |
|
484 stat_maxblocks=${maxblocks} |
|
485 fi |
|
486 |
|
487 stat_bytes=`expr ${stat_bytes} + ${lbytes}` |
|
488 stat_blocks=`expr ${stat_blocks} + ${lblocks}` |
|
489 stat_runs=`expr ${stat_runs} + ${lruns}` |
|
490 } |
|
491 |
|
492 stat_print() |
|
493 { |
|
494 if [ ${stat_runs} -gt 0 ]; then |
|
495 stat_avgbytes=`expr "${stat_bytes}" / "${stat_runs}"` |
|
496 stat_avgblocks=`expr "${stat_blocks}" / "${stat_runs}"` |
|
497 |
|
498 echo |
|
499 echo "$1 statistics:" |
|
500 echo "Leaked bytes: ${stat_minbytes} min, ${stat_avgbytes} avg, ${stat_maxbytes} max" |
|
501 echo "Leaked blocks: ${stat_minblocks} min, ${stat_avgblocks} avg, ${stat_maxblocks} max" |
|
502 echo "Total runs: ${stat_runs}" |
|
503 echo |
|
504 fi |
|
505 } |
|
506 |
|
507 ########################## run_ciphers_server ########################## |
|
508 # local shell function to test server part of code (selfserv) |
|
509 ######################################################################## |
|
510 run_ciphers_server() |
|
511 { |
|
512 html_head "Memory leak checking - server" |
|
513 |
|
514 stat_clear |
|
515 |
|
516 client_mode="NORMAL" |
|
517 for server_mode in ${MODE_LIST}; do |
|
518 set_test_mode |
|
519 |
|
520 for freebl in ${FREEBL_LIST}; do |
|
521 set_freebl || continue |
|
522 |
|
523 LOGNAME=server-${BIT_NAME}-${freebl}-${server_mode} |
|
524 LOGFILE=${LOGDIR}/${LOGNAME}.log |
|
525 echo "Running ${LOGNAME}" |
|
526 |
|
527 ( |
|
528 run_selfserv_dbg 2>> ${LOGFILE} & |
|
529 sleep 5 |
|
530 run_strsclnt |
|
531 ) |
|
532 |
|
533 sleep 20 |
|
534 clear_freebl |
|
535 |
|
536 log_parse |
|
537 ret=$? |
|
538 |
|
539 html_msg ${ret} 0 "${LOGNAME}" "produced a returncode of $ret, expected is 0" |
|
540 done |
|
541 done |
|
542 |
|
543 stat_print "Selfserv" |
|
544 |
|
545 html "</TABLE><BR>" |
|
546 } |
|
547 |
|
548 ########################## run_ciphers_client ########################## |
|
549 # local shell function to test client part of code (strsclnt) |
|
550 ######################################################################## |
|
551 run_ciphers_client() |
|
552 { |
|
553 html_head "Memory leak checking - client" |
|
554 |
|
555 stat_clear |
|
556 |
|
557 server_mode="NORMAL" |
|
558 for client_mode in ${MODE_LIST}; do |
|
559 set_test_mode |
|
560 |
|
561 for freebl in ${FREEBL_LIST}; do |
|
562 set_freebl || continue |
|
563 |
|
564 LOGNAME=client-${BIT_NAME}-${freebl}-${client_mode} |
|
565 LOGFILE=${LOGDIR}/${LOGNAME}.log |
|
566 echo "Running ${LOGNAME}" |
|
567 |
|
568 ( |
|
569 run_selfserv & |
|
570 sleep 5 |
|
571 run_strsclnt_dbg 2>> ${LOGFILE} |
|
572 ) |
|
573 |
|
574 sleep 20 |
|
575 clear_freebl |
|
576 |
|
577 log_parse |
|
578 ret=$? |
|
579 html_msg ${ret} 0 "${LOGNAME}" "produced a returncode of $ret, expected is 0" |
|
580 done |
|
581 done |
|
582 |
|
583 stat_print "Strsclnt" |
|
584 |
|
585 html "</TABLE><BR>" |
|
586 } |
|
587 |
|
588 ########################## parse_logfile_dbx ########################### |
|
589 # local shell function to parse and process logs from dbx |
|
590 ######################################################################## |
|
591 parse_logfile_dbx() |
|
592 { |
|
593 ${AWK} ' |
|
594 BEGIN { |
|
595 in_mel = 0 |
|
596 mel_line = 0 |
|
597 bytes = 0 |
|
598 lbytes = 0 |
|
599 minbytes = 9999999 |
|
600 maxbytes = 0 |
|
601 blocks = 0 |
|
602 lblocks = 0 |
|
603 minblocks = 9999999 |
|
604 maxblocks = 0 |
|
605 runs = 0 |
|
606 stack_string = "" |
|
607 bin_name = "" |
|
608 } |
|
609 /Memory Leak \(mel\):/ || |
|
610 /Possible memory leak -- address in block \(aib\):/ || |
|
611 /Block in use \(biu\):/ { |
|
612 in_mel = 1 |
|
613 stack_string = "" |
|
614 next |
|
615 } |
|
616 in_mel == 1 && /^$/ { |
|
617 print bin_name stack_string |
|
618 in_mel = 0 |
|
619 mel_line = 0 |
|
620 next |
|
621 } |
|
622 in_mel == 1 { |
|
623 mel_line += 1 |
|
624 } |
|
625 /Found leaked block of size/ { |
|
626 bytes += $6 |
|
627 blocks += 1 |
|
628 next |
|
629 } |
|
630 /Found .* leaked blocks/ { |
|
631 bytes += $8 |
|
632 blocks += $2 |
|
633 next |
|
634 } |
|
635 /Found block of size/ { |
|
636 bytes += $5 |
|
637 blocks += 1 |
|
638 next |
|
639 } |
|
640 /Found .* blocks totaling/ { |
|
641 bytes += $5 |
|
642 blocks += $2 |
|
643 next |
|
644 } |
|
645 mel_line > 2 { |
|
646 gsub(/\(\)/, "") |
|
647 new_line = $2 |
|
648 stack_string = "/" new_line stack_string |
|
649 next |
|
650 } |
|
651 /^Running: / { |
|
652 bin_name = $2 |
|
653 next |
|
654 } |
|
655 /execution completed/ { |
|
656 runs += 1 |
|
657 lbytes += bytes |
|
658 minbytes = (minbytes < bytes) ? minbytes : bytes |
|
659 maxbytes = (maxbytes > bytes) ? maxbytes : bytes |
|
660 bytes = 0 |
|
661 lblocks += blocks |
|
662 minblocks = (minblocks < blocks) ? minblocks : blocks |
|
663 maxblocks = (maxblocks > blocks) ? maxblocks : blocks |
|
664 blocks = 0 |
|
665 next |
|
666 } |
|
667 END { |
|
668 print "# " lbytes " bytes " lblocks " blocks in " runs " runs " \ |
|
669 minbytes " minbytes " maxbytes " maxbytes " minblocks " minblocks " \ |
|
670 maxblocks " maxblocks " > "/dev/stderr" |
|
671 }' 2> ${TMP_COUNT} |
|
672 |
|
673 stat_add |
|
674 } |
|
675 |
|
676 ######################## parse_logfile_valgrind ######################## |
|
677 # local shell function to parse and process logs from valgrind |
|
678 ######################################################################## |
|
679 parse_logfile_valgrind() |
|
680 { |
|
681 ${AWK} ' |
|
682 BEGIN { |
|
683 in_mel = 0 |
|
684 in_sum = 0 |
|
685 bytes = 0 |
|
686 lbytes = 0 |
|
687 minbytes = 9999999 |
|
688 maxbytes = 0 |
|
689 blocks = 0 |
|
690 lblocks = 0 |
|
691 minblocks = 9999999 |
|
692 maxblocks = 0 |
|
693 runs = 0 |
|
694 stack_string = "" |
|
695 bin_name = "" |
|
696 } |
|
697 !/==[0-9]*==/ { |
|
698 if ( $1 == "Running:" ) |
|
699 bin_name = $2 |
|
700 bin_nf = split(bin_name, bin_fields, "/") |
|
701 bin_name = bin_fields[bin_nf] |
|
702 next |
|
703 } |
|
704 /blocks are/ { |
|
705 in_mel = 1 |
|
706 stack_string = "" |
|
707 next |
|
708 } |
|
709 /LEAK SUMMARY/ { |
|
710 in_sum = 1 |
|
711 next |
|
712 } |
|
713 /^==[0-9]*== *$/ { |
|
714 if (in_mel) |
|
715 print bin_name stack_string |
|
716 if (in_sum) { |
|
717 runs += 1 |
|
718 lbytes += bytes |
|
719 minbytes = (minbytes < bytes) ? minbytes : bytes |
|
720 maxbytes = (maxbytes > bytes) ? maxbytes : bytes |
|
721 bytes = 0 |
|
722 lblocks += blocks |
|
723 minblocks = (minblocks < blocks) ? minblocks : blocks |
|
724 maxblocks = (maxblocks > blocks) ? maxblocks : blocks |
|
725 blocks = 0 |
|
726 } |
|
727 in_sum = 0 |
|
728 in_mel = 0 |
|
729 next |
|
730 } |
|
731 in_mel == 1 { |
|
732 new_line = $4 |
|
733 if ( new_line == "(within") |
|
734 new_line = "*" |
|
735 stack_string = "/" new_line stack_string |
|
736 } |
|
737 in_sum == 1 { |
|
738 for (i = 2; i <= NF; i++) { |
|
739 if ($i == "bytes") { |
|
740 str = $(i - 1) |
|
741 gsub(",", "", str) |
|
742 bytes += str |
|
743 } |
|
744 if ($i == "blocks.") { |
|
745 str = $(i - 1) |
|
746 gsub(",", "", str) |
|
747 blocks += str |
|
748 } |
|
749 } |
|
750 } |
|
751 END { |
|
752 print "# " lbytes " bytes " lblocks " blocks in " runs " runs " \ |
|
753 minbytes " minbytes " maxbytes " maxbytes " minblocks " minblocks " \ |
|
754 maxblocks " maxblocks " > "/dev/stderr" |
|
755 }' 2> ${TMP_COUNT} |
|
756 |
|
757 stat_add |
|
758 } |
|
759 |
|
760 ############################# check_ignored ############################ |
|
761 # local shell function to check all stacks if they are not ignored |
|
762 ######################################################################## |
|
763 check_ignored() |
|
764 { |
|
765 ${AWK} -F/ ' |
|
766 BEGIN { |
|
767 ignore = "'${IGNORED_STACKS}'" |
|
768 # read in the ignore file |
|
769 BUGNUM = "" |
|
770 count = 0 |
|
771 new = 0 |
|
772 while ((getline line < ignore) > 0) { |
|
773 if (line ~ "^#[0-9]+") { |
|
774 BUGNUM = line |
|
775 } else if (line ~ "^#") { |
|
776 continue |
|
777 } else if (line == "") { |
|
778 continue |
|
779 } else { |
|
780 bugnum_array[count] = BUGNUM |
|
781 # Create a regular expression for the ignored stack: |
|
782 # replace * with % so we can later replace them with regular expressions |
|
783 # without messing up everything (the regular expressions contain *) |
|
784 gsub("\\*", "%", line) |
|
785 # replace %% with .* |
|
786 gsub("%%", ".*", line) |
|
787 # replace % with [^/]* |
|
788 gsub("%", "[^/]*", line) |
|
789 # add ^ at the beginning |
|
790 # add $ at the end |
|
791 line_array[count] = "^" line "$" |
|
792 count++ |
|
793 } |
|
794 } |
|
795 } |
|
796 { |
|
797 match_found = 0 |
|
798 # Look for matching ignored stack |
|
799 for (i = 0; i < count; i++) { |
|
800 if ($0 ~ line_array[i]) { |
|
801 # found a match |
|
802 match_found = 1 |
|
803 bug_found = bugnum_array[i] |
|
804 break |
|
805 } |
|
806 } |
|
807 # Process result |
|
808 if (match_found == 1 ) { |
|
809 if (bug_found != "") { |
|
810 print "IGNORED STACK (" bug_found "): " $0 |
|
811 } else { |
|
812 print "IGNORED STACK: " $0 |
|
813 } |
|
814 } else { |
|
815 print "NEW STACK: " $0 |
|
816 new = 1 |
|
817 } |
|
818 } |
|
819 END { |
|
820 exit new |
|
821 }' |
|
822 ret=$? |
|
823 return $ret |
|
824 } |
|
825 |
|
826 ############################### parse_log ############################## |
|
827 # local shell function to parse log file |
|
828 ######################################################################## |
|
829 log_parse() |
|
830 { |
|
831 ${PARSE_LOGFILE} < ${LOGFILE} > ${TMP_STACKS} |
|
832 echo "${SCRIPTNAME}: Processing log ${LOGNAME}:" > ${TMP_SORTED} |
|
833 cat ${TMP_STACKS} | sort -u | check_ignored >> ${TMP_SORTED} |
|
834 ret=$? |
|
835 echo >> ${TMP_SORTED} |
|
836 |
|
837 cat ${TMP_SORTED} | tee -a ${FOUNDLEAKS} |
|
838 rm ${TMP_STACKS} ${TMP_SORTED} |
|
839 |
|
840 return ${ret} |
|
841 } |
|
842 |
|
843 ############################## cnt_total ############################### |
|
844 # local shell function to count total leaked bytes |
|
845 ######################################################################## |
|
846 cnt_total() |
|
847 { |
|
848 echo "" |
|
849 echo "TinderboxPrint:${OPT} Lk bytes: ${tbytes}" |
|
850 echo "TinderboxPrint:${OPT} Lk blocks: ${tblocks}" |
|
851 echo "TinderboxPrint:${OPT} # of runs: ${truns}" |
|
852 echo "" |
|
853 } |
|
854 |
|
855 ############################### run_ocsp ############################### |
|
856 # local shell function to run ocsp tests |
|
857 ######################################################################## |
|
858 run_ocsp() |
|
859 { |
|
860 stat_clear |
|
861 |
|
862 cd ${QADIR}/iopr |
|
863 . ./ocsp_iopr.sh |
|
864 ocsp_iopr_run |
|
865 |
|
866 stat_print "Ocspclnt" |
|
867 } |
|
868 |
|
869 ############################## run_chains ############################## |
|
870 # local shell function to run PKIX certificate chains tests |
|
871 ######################################################################## |
|
872 run_chains() |
|
873 { |
|
874 stat_clear |
|
875 |
|
876 LOGNAME="chains" |
|
877 LOGFILE=${LOGDIR}/chains.log |
|
878 |
|
879 . ${QADIR}/chains/chains.sh |
|
880 |
|
881 stat_print "Chains" |
|
882 } |
|
883 |
|
884 ############################## run_chains ############################## |
|
885 # local shell function to run memory leak tests |
|
886 # |
|
887 # NSS_MEMLEAK_TESTS - list of tests to run, if not defined before, |
|
888 # then is redefined to default list |
|
889 ######################################################################## |
|
890 memleak_run_tests() |
|
891 { |
|
892 nss_memleak_tests="ssl_server ssl_client chains ocsp" |
|
893 NSS_MEMLEAK_TESTS="${NSS_MEMLEAK_TESTS:-$nss_memleak_tests}" |
|
894 |
|
895 for MEMLEAK_TEST in ${NSS_MEMLEAK_TESTS} |
|
896 do |
|
897 case "${MEMLEAK_TEST}" in |
|
898 "ssl_server") |
|
899 run_ciphers_server |
|
900 ;; |
|
901 "ssl_client") |
|
902 run_ciphers_client |
|
903 ;; |
|
904 "chains") |
|
905 run_chains |
|
906 ;; |
|
907 "ocsp") |
|
908 run_ocsp |
|
909 ;; |
|
910 esac |
|
911 done |
|
912 } |
|
913 |
|
914 ################################# main ################################# |
|
915 |
|
916 memleak_init |
|
917 memleak_run_tests |
|
918 cnt_total |
|
919 memleak_cleanup |
|
920 |