From: Karel Zak Date: Wed, 27 Nov 2024 13:02:25 +0000 (+0100) Subject: include/optstr: improve optstr parsing X-Git-Tag: v2.42-start~130^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=02defa3e3f0c50171b5621af6426b58cd2c6c343;p=thirdparty%2Futil-linux.git include/optstr: improve optstr parsing * make sure option cannot start with '=' * add ul_optstr_is_valid() * add regression test Signed-off-by: Karel Zak --- diff --git a/include/strutils.h b/include/strutils.h index e5ddbcf1b..aa8c002d5 100644 --- a/include/strutils.h +++ b/include/strutils.h @@ -456,5 +456,6 @@ extern int skip_fline(FILE *fp); extern int ul_stralnumcmp(const char *p1, const char *p2); extern int ul_optstr_next(char **optstr, char **name, size_t *namesz, char **value, size_t *valsz); +extern int ul_optstr_is_valid(const char *optstr); #endif diff --git a/lib/strutils.c b/lib/strutils.c index e3a059145..4590aa911 100644 --- a/lib/strutils.c +++ b/lib/strutils.c @@ -1217,6 +1217,8 @@ int ul_optstr_next(char **optstr, char **name, size_t *namesz, optstr0++; for (p = optstr0; p && *p; p++) { + if (!start && *p == '=') + return -EINVAL; if (!start) start = p; /* beginning of the option item */ if (*p == '"') @@ -1252,6 +1254,15 @@ int ul_optstr_next(char **optstr, char **name, size_t *namesz, return 1; /* end of optstr */ } +int ul_optstr_is_valid(const char *optstr) +{ + int rc; + char *p = (char *) optstr; + + while ((rc = ul_optstr_next(&p, NULL, NULL, NULL, NULL)) == 0); + return rc < 0 ? 0 : 1; +} + #ifdef TEST_PROGRAM_STRUTILS #include "cctype.h" @@ -1430,6 +1441,24 @@ int main(int argc, char *argv[]) printf("str: '%s'\n", p); } while ((p = ul_next_string(p, end))); + return EXIT_SUCCESS; + + } else if (argc == 3 && strcmp(argv[1], "--optstr") == 0) { + + size_t namesz, valsz; + char *name = NULL, *val = NULL; + char *p = argv[2]; + int rc; + + if (!ul_optstr_is_valid(p)) + errx(EXIT_FAILURE, _("unsupported option format: %s"), p); + + while ((rc = ul_optstr_next(&p, &name, &namesz, &val, &valsz)) == 0) { + printf("'%.*s' : '%.*s'\n", (int) namesz, name, + (int) valsz, val); + } + if (rc == 1) + return EXIT_SUCCESS; } else { fprintf(stderr, "usage: %1$s --size [suffix]\n" " %1$s --cmp-paths \n" diff --git a/tests/expected/misc/optstr b/tests/expected/misc/optstr new file mode 100644 index 000000000..86d094ebf --- /dev/null +++ b/tests/expected/misc/optstr @@ -0,0 +1,4 @@ +'key' : '"v,a,l,u,e"' +'foo' : '' +'bar' : 'BAR' +'"/path/with/,comma"' : 'data' diff --git a/tests/ts/misc/optstr b/tests/ts/misc/optstr new file mode 100755 index 000000000..edc2f4cf1 --- /dev/null +++ b/tests/ts/misc/optstr @@ -0,0 +1,14 @@ +#!/bin/bash + +TS_TOPDIR="${0%/*}/../.." +TS_DESC="optstr" + +. "$TS_TOPDIR"/functions.sh +ts_init "$*" + +ts_check_test_command "$TS_HELPER_STRUTILS" + +$TS_HELPER_STRUTILS --optstr "key=\"v,a,l,u,e\",foo,bar=BAR,\"/path/with/,comma\"=data" >> $TS_OUTPUT 2>> $TS_ERRLOG + +ts_finalize +