From: Alain Spineux Date: Thu, 23 Apr 2020 14:32:40 +0000 (+0200) Subject: BEE Backport bacula/src/lib/scan.c X-Git-Tag: Release-11.3.2~1785 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d099bb4f79c2d1bbdec3917f8f1aa954b2ab9c58;p=thirdparty%2Fbacula.git BEE Backport bacula/src/lib/scan.c This commit is the result of the squash of the following main commits: Author: Alain Spineux Date: Mon Apr 8 13:57:48 2019 +0200 new scan_string() to be used where "old" bsscanf() don't work Author: Eric Bollengier Date: Sun Apr 7 11:56:45 2019 +0200 Make bsscanf compatible with the old bsscanf Author: Eric Bollengier Date: Fri Apr 5 20:38:00 2019 +0200 Fix bsscanf again with empty strings at the end of line Author: Alain Spineux Date: Fri Apr 5 13:56:08 2019 +0200 fix bsscanf continue parsing + more unittest - error is used for error and not for a "no match" - error in the format string like %b where 'b' is not a valid format character - the return code let you know HOW many "real" matches you got - lot of new tests - check respect string limit - check negative numbers, up to the 63/64 bit limits Author: Eric Bollengier Date: Fri Apr 5 17:48:19 2019 +0200 Fix issue with scan Author: Alain Spineux Date: Fri Mar 29 14:28:11 2019 +0100 Fix bsscanf() returns the wrong number of conversion - returns the right number of successful conversion bsscanf("1", "%d %d",..)==2 must be 1 - mimic sscanf for empty strings - return EOF instead of doing a segfault when the input or fmt string are NULL Author: Alain Spineux Date: Fri Mar 29 09:32:09 2019 +0100 regress: Add unittest scan_test to test bsscanf() in scan.c - test bsscanf() Author: Kern Sibbald Date: Mon Feb 7 15:01:09 2011 +0100 Add negative numbers to bsscanf --- diff --git a/bacula/src/lib/scan.c b/bacula/src/lib/scan.c index 4a8d262897..b09e399f0f 100644 --- a/bacula/src/lib/scan.c +++ b/bacula/src/lib/scan.c @@ -345,6 +345,8 @@ void split_path_and_filename(const char *fname, POOLMEM **path, int *pnl, * Note, BIG is the default maximum length when no length * has been specified for %s. If it is not big enough, then * simply add a length such as %10000s. + * + * Don't use this bsscanf() anymore, use scan_string() instead */ const int BIG = 1000; int bsscanf(const char *buf, const char *fmt, ...) @@ -492,6 +494,183 @@ switch_top: return count; } +/* + * scan_string() is more strict than the standard sscanf() function. + * The format sting must match exactly ! If so the function + * return then number or argument (%) parsed, else it return EOF + * One space in the format string match one or more spaces in the input string + * see the unittest below to see how it works. + * + */ +int scan_string(const char *buf, const char *fmt, ...) +{ + va_list ap; + int count = 0; + void *vp; + char *cp; + int l = 0; + int max_len = BIG; + uint64_t value; + bool error = false; + bool negative; + + if ((buf==NULL || fmt==NULL)) { + return EOF; // original sscanf segfault + } + + if (*buf=='\0' && *fmt!='\0') { + return EOF; // mimic sscanf + } + + va_start(ap, fmt); + while (*fmt && !error) { +// Dmsg1(000, "fmt=%c\n", *fmt); + if (*fmt == '%') { + fmt++; +// Dmsg1(000, "Got %% nxt=%c\n", *fmt); +switch_top: + switch (*fmt++) { + case 'u': + value = 0; + if (!B_ISDIGIT(*buf)) { + error = true; + break; + } + while (B_ISDIGIT(*buf)) { + value = B_TIMES10(value) + *buf++ - '0'; + } + vp = (void *)va_arg(ap, void *); +// Dmsg2(000, "val=%lld at 0x%lx\n", value, (long unsigned)vp); + if (l == 0) { + *((int *)vp) = (int)value; + } else if (l == 1) { + *((uint32_t *)vp) = (uint32_t)value; +// Dmsg0(000, "Store 32 bit int\n"); + } else { + *((uint64_t *)vp) = (uint64_t)value; +// Dmsg0(000, "Store 64 bit int\n"); + } + count++; + l = 0; + break; + case 'd': + value = 0; + if (*buf == '-') { + negative = true; + buf++; + } else { + negative = false; + } + if (!B_ISDIGIT(*buf)) { + error = true; + break; + } + while (B_ISDIGIT(*buf)) { + value = B_TIMES10(value) + *buf++ - '0'; + } + if (negative) { + value = -value; + } + vp = (void *)va_arg(ap, void *); +// Dmsg2(000, "val=%lld at 0x%lx\n", value, (long unsigned)vp); + if (l == 0) { + *((int *)vp) = (int)value; + } else if (l == 1) { + *((int32_t *)vp) = (int32_t)value; +// Dmsg0(000, "Store 32 bit int\n"); + } else { + *((int64_t *)vp) = (int64_t)value; +// Dmsg0(000, "Store 64 bit int\n"); + } + count++; + l = 0; + break; + case 'l': +// Dmsg0(000, "got l\n"); + l = 1; + if (*fmt == 'l') { + l++; + fmt++; + } + if (*fmt == 'd' || *fmt == 'u') { + goto switch_top; + } +// Dmsg1(000, "fmt=%c !=d,u\n", *fmt); + error = true; + break; + case 'q': + l = 2; + if (*fmt == 'd' || *fmt == 'u') { + goto switch_top; + } +// Dmsg1(000, "fmt=%c !=d,u\n", *fmt); + error = true; + break; + case 's': +// Dmsg1(000, "Store string max_len=%d\n", max_len); + cp = (char *)va_arg(ap, char *); + while (*buf && !B_ISSPACE(*buf) && max_len-- > 0) { + *cp++ = *buf++; + } + *cp = 0; + count++; + max_len = BIG; + break; + case 'c': + cp = (char *)va_arg(ap, char *); + if (*buf == '\0') { + error = true; + break; + } + *cp = *buf++; + count++; + break; + case '%': + if (*buf++ != '%') { + error = true; + } + break; + default: + fmt--; + max_len = 0; + while (B_ISDIGIT(*fmt)) { + max_len = B_TIMES10(max_len) + *fmt++ - '0'; + } +// Dmsg1(000, "Default max_len=%d\n", max_len); + if (*fmt == 's') { + goto switch_top; + } +// Dmsg1(000, "Default c=%c\n", *fmt); + error = true; + break; /* error: unknown format */ + } + continue; + + /* White space eats ONE or more whitespace */ + } else if (B_ISSPACE(*fmt)) { + /* Ignore extra white space in the format string */ + while (B_ISSPACE(*fmt)) fmt++; + if (!B_ISSPACE(*buf)) { + error = true; + } + while (B_ISSPACE(*buf)) { + buf++; + } + /* Plain text must match */ + } else if (*buf++ != *fmt++) { +// Dmsg2(000, "Mismatch buf=%c fmt=%c\n", *--buf, *--fmt); + error = true; + break; + } + } + va_end(ap); +// Dmsg2(000, "Error=%d count=%d\n", error, count); + if (error) { + count = -1; + } + return count; +} + /* * Return next name from a comma separated list. Note, this * routine is destructive because it stored 0 at the end @@ -545,76 +724,270 @@ char *next_name(char **s) } #ifdef TEST_PROGRAM +#include "unittests.h" + +#undef sscanf + int main(int argc, char *argv[]) { - char buf[100]; - uint32_t val32; - uint64_t val64; - uint32_t FirstIndex, LastIndex, StartFile, EndFile, StartBlock, EndBlock; - char Job[200]; - int cnt; - char *helloreq= "Hello *UserAgent* calling\n"; - char *hello = "Hello %127s calling\n"; - char *catreq = -"CatReq Job=NightlySave.2004-06-11_19.11.32 CreateJobMedia FirstIndex=1 LastIndex=114 StartFile=0 EndFile=0 StartBlock=208 EndBlock=2903248"; -static char Create_job_media[] = "CatReq Job=%127s CreateJobMedia " - "FirstIndex=%u LastIndex=%u StartFile=%u EndFile=%u " - "StartBlock=%u EndBlock=%u\n"; -static char OK_media[] = "1000 OK VolName=%127s VolJobs=%u VolFiles=%u" - " VolBlocks=%u VolBytes=%" lld " VolMounts=%u VolErrors=%u VolWrites=%u" - " MaxVolBytes=%" lld " VolCapacityBytes=%" lld " VolStatus=%20s" - " Slot=%d MaxVolJobs=%u MaxVolFiles=%u InChanger=%d" - " VolReadTime=%" lld " VolWriteTime=%" lld; - char *media = -"1000 OK VolName=TestVolume001 VolJobs=0 VolFiles=0 VolBlocks=0 VolBytes=1 VolMounts=0 VolErrors=0 VolWrites=0 MaxVolBytes=0 VolCapacityBytes=0 VolStatus=Append Slot=0 MaxVolJobs=0 MaxVolFiles=0 InChanger=1 VolReadTime=0 VolWriteTime=0"; -struct VOLUME_CAT_INFO { - /* Media info for the current Volume */ - uint32_t VolCatJobs; /* number of jobs on this Volume */ - uint32_t VolCatFiles; /* Number of files */ - uint32_t VolCatBlocks; /* Number of blocks */ - uint64_t VolCatBytes; /* Number of bytes written */ - uint32_t VolCatMounts; /* Number of mounts this volume */ - uint32_t VolCatErrors; /* Number of errors this volume */ - uint32_t VolCatWrites; /* Number of writes this volume */ - uint32_t VolCatReads; /* Number of reads this volume */ - uint64_t VolCatRBytes; /* Number of bytes read */ - uint32_t VolCatRecycles; /* Number of recycles this volume */ - int32_t Slot; /* Slot in changer */ - bool InChanger; /* Set if vol in current magazine */ - uint32_t VolCatMaxJobs; /* Maximum Jobs to write to volume */ - uint32_t VolCatMaxFiles; /* Maximum files to write to volume */ - uint64_t VolCatMaxBytes; /* Max bytes to write to volume */ - uint64_t VolCatCapacityBytes; /* capacity estimate */ - uint64_t VolReadTime; /* time spent reading */ - uint64_t VolWriteTime; /* time spent writing this Volume */ - char VolCatStatus[20]; /* Volume status */ - char VolCatName[MAX_NAME_LENGTH]; /* Desired volume to mount */ -}; - struct VOLUME_CAT_INFO vol; - -#ifdef xxx - bsscanf("Hello_world 123 1234", "%120s %ld %lld", buf, &val32, &val64); - printf("%s %d %lld\n", buf, val32, val64); - - *Job=0; - cnt = bsscanf(catreq, Create_job_media, &Job, - &FirstIndex, &LastIndex, &StartFile, &EndFile, - &StartBlock, &EndBlock); - printf("cnt=%d Job=%s\n", cnt, Job); - cnt = bsscanf(helloreq, hello, &Job); - printf("cnt=%d Agent=%s\n", cnt, Job); -#endif - cnt = bsscanf(media, OK_media, - vol.VolCatName, - &vol.VolCatJobs, &vol.VolCatFiles, - &vol.VolCatBlocks, &vol.VolCatBytes, - &vol.VolCatMounts, &vol.VolCatErrors, - &vol.VolCatWrites, &vol.VolCatMaxBytes, - &vol.VolCatCapacityBytes, vol.VolCatStatus, - &vol.Slot, &vol.VolCatMaxJobs, &vol.VolCatMaxFiles, - &vol.InChanger, &vol.VolReadTime, &vol.VolWriteTime); - printf("cnt=%d Vol=%s\n", cnt, vol.VolCatName); + Unittests test1("bsscanf_test"); + { + int cnt; + char buf[512]; + int32_t a = -99; + + cnt=bsscanf("CatReq JobId=5 CreateFileMedia\n", "CatReq JobId=%ld CreateFileMedia\n", &a); + ok(cnt == 1 && a==5, "[CatReq JobId=5 CreateFileMedia] => [CatReq JobId=%ld CreateFileMedia]"); + + cnt=bsscanf("CatReq JobId=5 CreateJobMedia\n", "CatReq JobId=%ld CreateFileMedia\n", &a); + ok(cnt == -1, "[CatReq JobId=5 CreateJobMedia] => [CatReq JobId=%ld CreateFileMedia]"); + + uint32_t FirstIndex, LastIndex, StartFile, EndFile, StartBlock, EndBlock; + const char *catreq = "CatReq Job=NightlySave.2004-06-11_19.11.32 CreateJobMedia FirstIndex=1 LastIndex=114 StartFile=0 EndFile=0 StartBlock=208 EndBlock=2903248"; + const char *Create_job_media = "CatReq Job=%127s CreateJobMedia " + "FirstIndex=%u LastIndex=%u StartFile=%u EndFile=%u " + "StartBlock=%u EndBlock=%u\n"; + memset(buf, '\0', sizeof(buf)); + FirstIndex=LastIndex=StartFile=EndFile=StartBlock=EndBlock=231170; + cnt = bsscanf(catreq, Create_job_media, &buf, + &FirstIndex, &LastIndex, &StartFile, &EndFile, + &StartBlock, &EndBlock); + ok(cnt==7 && strcmp(buf, "NightlySave.2004-06-11_19.11.32")==0 && + FirstIndex==1 && LastIndex==114 && StartFile==0 && + EndFile==0 && StartBlock==208 && EndBlock==2903248, "CatReq Job"); + + } + + Unittests test2("scan_string_test"); + { + int a,b,c,d,e,f; + int u; + int32_t cnt; + int64_t g; + char buf[512]; + + strcpy(buf, "xxx"); + cnt=scan_string("string=", "string=%256s", buf); + ok(cnt==1 && *buf == 0, "[string=] => [string=%256s]"); + //Dmsg2(0, "cnt=%d buf=%s\n", cnt, buf); + + a = b = c = d = e =f = g = -99; + cnt=scan_string("1 2 223 6 0\n", "%d %d %d %d %d %d %lld\n", + &a,&b,&c,&d,&e,&f,&g); + ok(cnt == -1, "[1 2 223 6 0] => [%d %d %d %d %d %d %lld]"); + + a = b = c = d = e =f = g = -99; + cnt=scan_string("1 2 -223 -0 0\n", "%d %d %d %d %lld\n", &a,&b,&c,&d,&g); + ok(cnt == 5 && a==1 && b==2 && c==-223 && d==0 && g==0, + "[1 2 -223 -0 0] => [%u %u %u %u %u %u %lld]"); + + u = 99; + cnt=scan_string("-223\n", "%u\n", &u); + ok(cnt == -1 && u == 99, "[-223] => [%u]"); + +// printf("%d %d %d %d %d %lld\n", cnt, a, b, c, d, g); + + Pmsg0(0, "Test scan_string bug ignore final 0\n"); + { + int a, b, cnt; + a=b=-99; + cnt=scan_string("123", "%d %d", &a, &b); /* Format error */ + ok(cnt==-1, "Check count [%d %d] => [123]"); + ok(a==123, "Check first value [%d %d] => [123]"); + ok(b==-99, "Check second value [%d %d] => [123] "); + } + + memset(buf, '\0', sizeof(buf)); a=b=-99; + cnt=scan_string("Hello world 123 456 end", "Hello %100s %d %d end", buf, &a, &b); + ok(cnt==3 && strcmp(buf, "world")==0 && a==123 && b==456, "multi space"); + + Pmsg0(0, "Test scan_string basic tests\n"); + { + char buf[100]; + int a, b, c, cnt; + uint32_t val32; + uint64_t val64; + int32_t sval32; + int64_t sval64; + + memset(buf, '\0', sizeof(buf)); a=b=-99; + cnt=scan_string("Hello world 123 456 end", "Hello %100s %d %d end", buf, &a, &b); + ok(cnt==3 && strcmp(buf, "world")==0 && a==123 && b==456, "test1"); + + memset(buf, '\0', sizeof(buf)); val64=val32=99; + cnt=scan_string("world 123 72057594037927953", "%120s %ld %lld", buf, &val32, &val64); + ok(cnt==3 && strcmp(buf, "world")==0 && val32==123 && val64==72057594037927953, "test2"); + + + memset(buf, '\0', sizeof(buf)); a=b=-99; + cnt=scan_string("Hello world 123", "Hello %100s %d %d end", buf, &a, &b); + //ok(cnt==2 && strcmp(buf, "world")==0 && a==123 && b==-99, "one missing"); // scanf compatible + ok(cnt==-1 && strcmp(buf, "world")==0 && a==123 && b==-99, "one missing"); // scanf compatible + + a=b=-99; + cnt=scan_string("Hello % -123", "Hello %% %d", &a); + ok(cnt==1 && a==-123, "match %%"); + + a=b=-99; + cnt=scan_string("", "Hello %d %d end", &a, &b); + ok(cnt==-1 && a==-99 && b==-99, "empty string 1"); + + a=b=-99; + cnt=scan_string("", "%d", &a); + ok(cnt==-1 && a==-99, "empty string 2"); + + a=b=-99; + cnt=scan_string("", "", &a); + ok(cnt==0 && a==-99, "empty string and format string"); + + a=b=-99; + cnt=scan_string("Hello", "", &a); + ok(cnt==0 && a==-99, "empty string and format string"); + + // Original sscanf segfault if any of the format or the input string are NULL + // scan_string return EOF instead + + #if 1 + /* Float scan is not supported yet by scan_string */ + a=b=-99; + cnt=scan_string("3.14 17", "%d %d", &a, &b); + ok(cnt==-1 && a==3 && b==-99, "parse float instead of int"); + #endif + + a=b=c=-99; + cnt=scan_string("Hello 123 c=2", "Hello %d %d c=%d", &a, &b, &c); + ok(cnt==-1 && a==123 && b==-99, "bug continue parsing after a 'no match'"); + // printf("%d %d %d %d\n", cnt, a, b, c); + + a=b=c=-99; + cnt=scan_string("Hello -123 456 end", "Hello %d %d", &a, &b); + ok(cnt==2 && a==-123 && b==456, "negative number"); + + #if 1 + a=b=c=-99; + cnt=scan_string("Hello -123 - 456", "Hello %d %d", &a, &b, &c); + ok(cnt==-1 && a==-123 && b==-99 && c==-99, "incomplete negative number"); + #endif + + a=b=c=-99; + cnt=scan_string("Hello -123 - 456", "Hello %d %d", &a, &b); + ok(cnt==-1 && a==-123, "incomplete negative number"); + + // 2^63==9223372036854775808 + val32=val64=sval32=sval64=99; + cnt=scan_string("9223372036854775809", "%lld", &val64); + ok(cnt==1 && val64==9223372036854775809UL, "long >63bits"); + + val32=val64=sval32=sval64=99; + cnt=scan_string("-9223372036854775807", "%lld", &sval64); + ok(cnt==1 && sval64==-9223372036854775807L, "unsigned long <63bits"); + + a=b=c=-99; memset(buf, 'A', sizeof(buf)); buf[sizeof(buf)-1]='\0'; + cnt=scan_string("Hello world", "Hello %2s", buf); + ok(cnt==1 && strcmp(buf, "wo")==0 && buf[3]=='A', "string limitation");// This match sscanf + + #if 0 + /* The format is not correct */ + a=b=c=-99; memset(buf, 'A', sizeof(buf)); buf[sizeof(buf)-1]='\0'; + cnt=scan_string("Hello world 123", "Hello %2s %d", buf, &a); + ok(cnt==1 && a==-99 && strcmp(buf, "wo")==0 && buf[3]=='A', "string limitation & stop matching"); // This match sscanf + #endif + a=b=c=-99; memset(buf, 'A', sizeof(buf)); buf[sizeof(buf)-1]='\0'; + cnt=scan_string("Hello world 123", "Hello %2s %d", buf, &a); + ok(cnt==-1 && a==-99 && strcmp(buf, "wo")==0 && buf[3]=='A', "string limitation & stop matching"); + + a=b=c=-99; memset(buf, 'A', sizeof(buf)); buf[sizeof(buf)-1]='\0'; + cnt=scan_string("Hello world", "Hello %2srld", buf); + ok(cnt==1 && strcmp(buf, "wo")==0 && buf[3]=='A', "string limitation weird 1");// This match sscanf + + a=b=c=-99; memset(buf, 'A', sizeof(buf)); buf[sizeof(buf)-1]='\0'; + cnt=scan_string("Hello world 123", "Hello %2srld %d", buf, &a); + ok(cnt==2 && a==123 && strcmp(buf, "wo")==0 && buf[3]=='A', "string limitation weird 2");// This match sscanf + + { + Pmsg0(0, "Test FD-SD hello\n"); + + char job_name[500]; + int fd_version, sd_version, tlspsk; + const char *s="Hello Bacula SD: Start Job backupXXX 14 tlspsk=100"; + cnt=-99, fd_version=-99, sd_version=-99, tlspsk=-99; + cnt=scan_string(s, "Hello Bacula SD: Start Job %127s %d %d tlspsk=%d", job_name, &fd_version, &sd_version, &tlspsk); + #if 0 + /* The format is incorrect, it should return -1 */ + ok(cnt==2 && strcmp(job_name, "backupXXX")==0 && fd_version==14 && sd_version==-99 && tlspsk==-99, "SD-FD hello fmt1"); + #endif + ok(cnt==-1 && strcmp(job_name, "backupXXX")==0 && fd_version==14, "SD-FD hello fmt1"); + // printf("%d %d %d %d %s\n", cnt, fd_version, sd_version, tlspsk, job_name); + + cnt=-99, fd_version=-99, sd_version=-99, tlspsk=-99; + cnt=scan_string(s, "Hello Bacula SD: Start Job %127s %d %d", job_name, &fd_version, &sd_version); + #if 0 + /* The format is incorrect, it should return -1 */ + ok(cnt==2 && strcmp(job_name, "backupXXX")==0 && fd_version==14 && sd_version==-99 && tlspsk==-99, "SD-FD hello fmt2"); + #endif + ok(cnt==-1 && strcmp(job_name, "backupXXX")==0 && fd_version==14, "SD-FD hello fmt2"); + + cnt=-99, fd_version=-99, sd_version=-99, tlspsk=-99; + cnt=scan_string(s, "Hello Bacula SD: Start Job %127s %d tlspsk=%d", job_name, &fd_version, &tlspsk); + ok(cnt==3 && strcmp(job_name, "backupXXX")==0 && fd_version==14 && sd_version==-99 && tlspsk==100, "SD-FD hello fmt3"); + + cnt=-99, fd_version=-99, sd_version=-99, tlspsk=-99; + cnt=scan_string(s, "Hello Bacula SD: Start Job %127s %d", job_name, &fd_version); + ok(cnt==2 && strcmp(job_name, "backupXXX")==0 && fd_version==14 && sd_version==-99 && tlspsk==-99, "SD-FD hello fmt4"); + + cnt=-99, fd_version=-99, sd_version=-99, tlspsk=-99; + cnt=scan_string(s, "Hello FD: Bacula Storage calling Start Job %127s %d", job_name, &sd_version); + ok(cnt==-1 && fd_version==-99 && sd_version==-99 && tlspsk==-99, "SD-FD hello fmt5"); + } + + Pmsg0(0, "Test bscanf vs sscanf behavior, all are expected to return an error\n"); + memset(buf, '\0', sizeof(buf)); a=b=-99; + cnt=scan_string("DO YOU HAVE FIRE", "NO MATCH"); // => cnt==0 + ok(cnt==-1, "when literal dont match"); + + // BUT !!! + cnt=scan_string("Literal", "Literal"); + ok(cnt==0, "literal (strcmp like)"); + + /* scan_string parameters order: string_to_test, pattern */ + Pmsg0(0, "Test scan_string test starting with literal\n"); + cnt=scan_string("YES", "NO"); + ok(cnt==-1, "wrong literal YES NO"); + + cnt=scan_string("Hello World", "Hello Format"); + ok(cnt==-1, "different end"); + + cnt=scan_string("Hello", "HelloFormat"); + ok(cnt==-1, "end missing in format (format incomplete)"); + + cnt=scan_string("Hello", "Hello Format"); + ok(cnt==-1, "end missing in format with space (format incomplete)"); + + cnt=scan_string("Hello World", "Hello"); + ok(cnt==0, "format shorter than string"); + + cnt=scan_string("Hello World", "Hello %d", &a); + #if 0 + /* the format is not valid */ + ok(cnt==0, "format shorter with try to match"); + #endif + ok(cnt==-1, "format shorter with try to match"); + + a = -99; + cnt=scan_string("3000 OK Hello 30005", "3000 OK Hello %d", &a); + ok(cnt==1 && a == 30005, "[3000 OK Hello 30005] => [3000 OK Hello %d]"); + Dmsg2(0, "cnt=%d a=%d\n", cnt, a); + + a = -99; strcpy(buf, "xxx"); + cnt=scan_string("string=", "string=%256s", buf); + ok(cnt==1 && *buf == 0, "[string=] => [string=%256s]"); + Dmsg2(0, "cnt=%d buf=%s\n", cnt, buf); + + } + } + + return report(); } #endif