1#!/bin/sh 2# Use Failmalloc to test behaviour in the face of out-of-memory conditions. 3# The test runs a binary multiple times while configuring Failmalloc to fail a 4# different malloc() call each time, while looking for abnormal program exits 5# due to segfaults. See https://www.nongnu.org/failmalloc/ 6# 7# Ideally, it would ensure that the test binary returns an error code on each 8# failure, but this often doesn't happen. This is a problem that should be 9# rectified, but the API doesn't allow returning an error code in many 10# functions that could encounter a problem. The issue could be solved in more 11# cases with more judicious use of log calls with EXIF_LOG_CODE_NO_MEMORY 12# codes. 13# 14# Copyright (C) 2018-2021 Dan Fandrich <dan@coneharvesters.com>, et. al. 15# SPDX-License-Identifier: LGPL-2.0-or-later 16 17srcdir="${srcdir:-.}" 18 19VERBOSE= 20if [ "$1" = "-v" ] ; then 21 VERBOSE=1 22fi 23 24if [ x"$FAILMALLOC_PATH" = x ]; then 25 echo "libfailmalloc is not available" 26 exit 77 27fi 28 29BINARY_PREFIX=./ 30if [ -e .libs/lt-test-value ]; then 31 # If libtool is in use, the normal "binary" is actually a shell script which 32 # would be interfered with by libfailmalloc. Instead, use the special lt- 33 # binary which should work properly. 34 BINARY_PREFIX=".libs/lt-" 35fi 36 37# Usage: failmalloc_binary_test #iterations binary <optional arguments> 38# FIXME: auto-determine #iterations by comparing the output of each run 39# with the output of a normal run, and exiting when that happens. 40failmalloc_binary_test () { 41 binary="$BINARY_PREFIX$2" 42 iterations="$1" 43 shift 44 shift 45 echo Checking "$binary" for "$iterations" iterations 46 for n in $(seq "$iterations"); do 47 test "$VERBOSE" = 1 && { echo "$n"; set -x; } 48 FAILMALLOC_INTERVAL="$n" LD_PRELOAD="${LD_PRELOAD:+$LD_PRELOAD:}$FAILMALLOC_PATH" "$binary" "$@" >/dev/null 49 s=$? 50 test "$VERBOSE" = 1 && set +x; 51 if test "$s" -ge 125; then 52 # Such status codes only happen due to termination due to a signal 53 # like SIGSEGV or ASAN errors (ignoring a couple that the shell 54 # itself produces). 55 echo "Abnormal binary exit status $s at malloc #$n on $binary" 56 echo FAILURE 57 exit 1 58 fi 59 done 60} 61 62# Make ASAN errors return a high number to differentiate them from regular test 63# errors (which are ignored). This only does something if ASAN was configured 64# in the build. 65export ASAN_OPTIONS="exitcode=125${ASAN_OPTIONS:+:$ASAN_OPTIONS}" 66 67# The number of iterations is determined empirically to be about twice as 68# high as the maximum number of mallocs performed by the test program in order 69# to avoid lowering code coverage in the case of future code changes that cause 70# more allocations. 71 72failmalloc_binary_test 700 test-mem 73failmalloc_binary_test 500 test-value 74 75for f in ${srcdir}/testdata/*jpg; do 76 echo "Testing `basename "$f"`" 77 failmalloc_binary_test 600 test-parse$EXEEXT "$f" 78done 79# N.B. adding the following binaries doesn't actually increase code coverage: 80# test-extract -o /dev/null 81# test-gps 82# test-mnote 83# test-parse --swap-byte-order 84 85echo PASSED 86