From: Daniel Stenberg Date: Fri, 4 Jul 2025 21:57:03 +0000 (+0200) Subject: runtests: support memory-limits per test X-Git-Tag: curl-8_15_0~71 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8724306e78b399917f38e161cf97592377f45e8d;p=thirdparty%2Fcurl.git runtests: support memory-limits per test The idea here is to set limits per test how many allocations and maximum amount of memory it is allowed to use. This is a means to make sure the number and total size of allocations are kept in check and don't mistakenly "blow up". If runtests.pl detects that the given limits have been exceeded it fails the test case with an error. The `` part now supports ``, and in this section two limits can be set for each test (verified in debug builds only): Allocations: [number of allocation calls] Maximum allocated: [maximum concurrent memory allocated] Default limits (used if nothing is set in the test file): Allocations: 1000 Maximum allocated: 1000000 Closes #17821 --- diff --git a/docs/tests/FILEFORMAT.md b/docs/tests/FILEFORMAT.md index e6da32a5cf..992717b190 100644 --- a/docs/tests/FILEFORMAT.md +++ b/docs/tests/FILEFORMAT.md @@ -699,6 +699,14 @@ test. `loadfile="filename"` makes loading the data from an external file. +### `` + +When this test runs and curl was built with debug enabled, runtests make sure +that the set limits are not exceeded. Supported limits: + + Allocations: [number of allocation calls] + Maximum allocated: [maximum concurrent memory allocated] + ### `` The file's contents must be identical to this after the test is complete. Use the mode="text" attribute if the output is in text mode on platforms that have diff --git a/tests/data/test1 b/tests/data/test1 index 4aa4d1b812..1fb3e05248 100644 --- a/tests/data/test1 +++ b/tests/data/test1 @@ -49,5 +49,9 @@ User-Agent: curl/%VERSION Accept: */* + +Allocations: 135 +Maximum allocated: 135415 + diff --git a/tests/data/test1129 b/tests/data/test1129 index 41b295563a..99e390c500 100644 --- a/tests/data/test1129 +++ b/tests/data/test1129 @@ -92,5 +92,8 @@ Content-Type: application/x-www-form-urlencoded Expect: 100-continue + +Maximum allocated: 3200000 + diff --git a/tests/data/test1156 b/tests/data/test1156 index 94fa469dce..3492694273 100644 --- a/tests/data/test1156 +++ b/tests/data/test1156 @@ -67,5 +67,8 @@ http://%HOSTIP:%HTTPPORT/want/%TESTNUMBER 0 + +Allocations: 1300 + diff --git a/tests/data/test1291 b/tests/data/test1291 index 794ed22d02..8d51138da2 100644 --- a/tests/data/test1291 +++ b/tests/data/test1291 @@ -38,5 +38,8 @@ XXXXXXXx 1 + +Allocations: 3100 + diff --git a/tests/data/test1559 b/tests/data/test1559 index c307f6447e..7217035317 100644 --- a/tests/data/test1559 +++ b/tests/data/test1559 @@ -40,6 +40,9 @@ CURLUPART_URL 10000000 bytes URL == 3 (Malformed input to a URL function) CURLUPART_SCHEME 10000000 bytes scheme == 3 (Malformed input to a URL function) CURLUPART_USER 10000000 bytes user == 3 (Malformed input to a URL function) + +Maximum allocated: 10010000 + diff --git a/tests/data/test1560 b/tests/data/test1560 index 8a991f9b9e..381faaa93a 100644 --- a/tests/data/test1560 +++ b/tests/data/test1560 @@ -38,5 +38,8 @@ lib%TESTNUMBER success + +Allocations: 3000 + diff --git a/tests/data/test1651 b/tests/data/test1651 index e552a8ad38..e7b725763a 100644 --- a/tests/data/test1651 +++ b/tests/data/test1651 @@ -18,5 +18,12 @@ unittest x509 parsing + + + +Allocations: 14000 + + + diff --git a/tests/data/test2302 b/tests/data/test2302 index 9ade6a1e52..01a8675369 100644 --- a/tests/data/test2302 +++ b/tests/data/test2302 @@ -66,5 +66,8 @@ Sec-WebSocket-Key: NDMyMTUzMjE2MzIxNzMyMQ== 68 65 6c 6c 6f RECFLAGS: 1 + +Maximum allocated: 1300000 + diff --git a/tests/data/test2303 b/tests/data/test2303 index 79cb4c2ad0..f6ed9a5f67 100644 --- a/tests/data/test2303 +++ b/tests/data/test2303 @@ -55,5 +55,8 @@ Sec-WebSocket-Key: NDMyMTUzMjE2MzIxNzMyMQ== 22 + +Maximum allocated: 1300000 + diff --git a/tests/data/test2601 b/tests/data/test2601 index 778f6c54a7..a6581a803f 100644 --- a/tests/data/test2601 +++ b/tests/data/test2601 @@ -19,4 +19,9 @@ unittest bufq unit tests + + +Allocations: 6300 + + diff --git a/tests/data/test3207 b/tests/data/test3207 index fe2e38f978..318f8c704a 100644 --- a/tests/data/test3207 +++ b/tests/data/test3207 @@ -171,5 +171,8 @@ https://localhost:%HTTPSPORT/%TESTNUMBER %CERTDIR/certs/test-ca.crt # Verify data after the test has been "shot" + +Allocations: 13300 + diff --git a/tests/data/test440 b/tests/data/test440 index ce9892967c..81cf738473 100644 --- a/tests/data/test440 +++ b/tests/data/test440 @@ -73,5 +73,8 @@ https://this.hsts.example./%TESTNUMBER 56 + +Allocations: 1100 + diff --git a/tests/data/test442 b/tests/data/test442 index 2787c02b6f..fb881d3b67 100644 --- a/tests/data/test442 +++ b/tests/data/test442 @@ -209,5 +209,8 @@ Accept: */* Cookie: name150=could-be-large-150; name149=could-be-large-149; name148=could-be-large-148; name147=could-be-large-147; name146=could-be-large-146; name145=could-be-large-145; name144=could-be-large-144; name143=could-be-large-143; name142=could-be-large-142; name141=could-be-large-141; name140=could-be-large-140; name139=could-be-large-139; name138=could-be-large-138; name137=could-be-large-137; name136=could-be-large-136; name135=could-be-large-135; name134=could-be-large-134; name133=could-be-large-133; name132=could-be-large-132; name131=could-be-large-131; name130=could-be-large-130; name129=could-be-large-129; name128=could-be-large-128; name127=could-be-large-127; name126=could-be-large-126; name125=could-be-large-125; name124=could-be-large-124; name123=could-be-large-123; name122=could-be-large-122; name121=could-be-large-121; name120=could-be-large-120; name119=could-be-large-119; name118=could-be-large-118; name117=could-be-large-117; name116=could-be-large-116; name115=could-be-large-115; name114=could-be-large-114; name113=could-be-large-113; name112=could-be-large-112; name111=could-be-large-111; name110=could-be-large-110; name109=could-be-large-109; name108=could-be-large-108; name107=could-be-large-107; name106=could-be-large-106; name105=could-be-large-105; name104=could-be-large-104; name103=could-be-large-103; name102=could-be-large-102; name101=could-be-large-101; name100=could-be-large-100; name99=could-be-large-99; name98=could-be-large-98; name97=could-be-large-97; name96=could-be-large-96; name95=could-be-large-95; name94=could-be-large-94; name93=could-be-large-93; name92=could-be-large-92; name91=could-be-large-91; name90=could-be-large-90; name89=could-be-large-89; name88=could-be-large-88; name87=could-be-large-87; name86=could-be-large-86; name85=could-be-large-85; name84=could-be-large-84; name83=could-be-large-83; name82=could-be-large-82; name81=could-be-large-81; name80=could-be-large-80; name79=could-be-large-79; name78=could-be-large-78; name77=could-be-large-77; name76=could-be-large-76; name75=could-be-large-75; name74=could-be-large-74; name73=could-be-large-73; name72=could-be-large-72; name71=could-be-large-71; name70=could-be-large-70; name69=could-be-large-69; name68=could-be-large-68; name67=could-be-large-67; name66=could-be-large-66; name65=could-be-large-65; name64=could-be-large-64; name63=could-be-large-63; name62=could-be-large-62; name61=could-be-large-61; name60=could-be-large-60; name59=could-be-large-59; name58=could-be-large-58; name57=could-be-large-57; name56=could-be-large-56; name55=could-be-large-55; name54=could-be-large-54; name53=could-be-large-53; name52=could-be-large-52; name51=could-be-large-51; name50=could-be-large-50; name49=could-be-large-49; name48=could-be-large-48; name47=could-be-large-47; name46=could-be-large-46; name45=could-be-large-45; name44=could-be-large-44; name43=could-be-large-43; name42=could-be-large-42; name41=could-be-large-41; name40=could-be-large-40; name39=could-be-large-39; name38=could-be-large-38; name37=could-be-large-37; name36=could-be-large-36; name35=could-be-large-35; name34=could-be-large-34; name33=could-be-large-33; name32=could-be-large-32; name31=could-be-large-31; name30=could-be-large-30; name29=could-be-large-29; name28=could-be-large-28; name27=could-be-large-27; name26=could-be-large-26; name25=could-be-large-25; name24=could-be-large-24; name23=could-be-large-23; name22=could-be-large-22; name21=could-be-large-21; name20=could-be-large-20; name19=could-be-large-19; name18=could-be-large-18; name17=could-be-large-17; name16=could-be-large-16; name15=could-be-large-15; name14=could-be-large-14; name13=could-be-large-13; name12=could-be-large-12; name11=could-be-large-11; name10=could-be-large-10; name9=could-be-large-9; name8=could-be-large-8; name7=could-be-large-7; name6=could-be-large-6; name5=could-be-large-5; name4=could-be-large-4; name3=could-be-large-3; name2=could-be-large-2; name1=could-be-large-1 + +Allocations: 1100 + diff --git a/tests/data/test445 b/tests/data/test445 index d573077b15..ec0b0e61ed 100644 --- a/tests/data/test445 +++ b/tests/data/test445 @@ -57,5 +57,8 @@ Refuse tunneling protocols through HTTP proxy 56 + +Allocations: 1700 + diff --git a/tests/data/test497 b/tests/data/test497 index dec1808f9b..02ec8e802f 100644 --- a/tests/data/test497 +++ b/tests/data/test497 @@ -52,5 +52,8 @@ Accept: */* 56 + +Allocations: 1900 + diff --git a/tests/data/test500 b/tests/data/test500 index c215318bc5..0534cae1e5 100644 --- a/tests/data/test500 +++ b/tests/data/test500 @@ -54,5 +54,9 @@ Host: %HOSTIP:%HTTPPORT Accept: */* + +Allocations: 80 +Maximum allocated: 33400 + diff --git a/tests/data/test575 b/tests/data/test575 index 35b65a3d6f..fbb7343d96 100644 --- a/tests/data/test575 +++ b/tests/data/test575 @@ -120,5 +120,8 @@ This file should have permissions 777 This is content of file "file.txt" Some junk ;-) This file does not really exist. + +Allocations: 1500 + diff --git a/tests/data/test747 b/tests/data/test747 index 6b541a4337..4397c7741c 100644 --- a/tests/data/test747 +++ b/tests/data/test747 @@ -52,5 +52,8 @@ Accept: */* 100 + +Allocations: 6000 + diff --git a/tests/data/test751 b/tests/data/test751 index ffc6df512f..21a3df2507 100644 --- a/tests/data/test751 +++ b/tests/data/test751 @@ -27,7 +27,11 @@ multi - add many easy handles -# Verify data after the test has been "shot" +# 1000 easy handles needs memory + +Maximum allocated: 6000000 +Allocations: 7000 + diff --git a/tests/data/test993 b/tests/data/test993 index 01248de339..2f5607b679 100644 --- a/tests/data/test993 +++ b/tests/data/test993 @@ -38,5 +38,8 @@ PASS secret LIST QUIT + +Allocations: 2200 + diff --git a/tests/runtests.pl b/tests/runtests.pl index db9054ba1f..39e9bca3f7 100755 --- a/tests/runtests.pl +++ b/tests/runtests.pl @@ -1698,6 +1698,48 @@ sub singletest_check { else { $ok .= "m"; } + my @more=`$memanalyze -v "$logdir/$MEMDUMP"`; + my $allocs; + my $max; + for(@more) { + if(/^Allocations: (\d+)/) { + $allocs = $1; + } + elsif(/^Maximum allocated: (\d+)/) { + $max = $1; + } + } + my @limits = getpart("verify", "limits"); + my $lim_allocs = 1000; # high default values + my $lim_max = 1000000; + for(@limits) { + if(/^Allocations: (\d+)/i) { + $lim_allocs = $1; + } + elsif(/^Maximum allocated: (\d+)/i) { + $lim_max = $1; + } + } + logmsg "did $allocs allocations, $lim_allocs allowed\n" + if($verbose); + + logmsg "allocated $max maximum, $lim_max allowed\n" + if($verbose); + + if($allocs > $lim_allocs) { + logmsg "\n** TOO MANY ALLOCS\n"; + logmsg "$lim_allocs allocations allowed, did $allocs\n"; + # timestamp test result verification end + $timevrfyend{$testnum} = Time::HiRes::time(); + return -1; + } + if($max > $lim_max) { + logmsg "\n** TOO MUCH TOTAL ALLOCATION\n"; + logmsg "$lim_max maximum allocation allowed, did $max\n"; + # timestamp test result verification end + $timevrfyend{$testnum} = Time::HiRes::time(); + return -1; + } } } else {