mirror of
https://git.code.sf.net/p/zint/code
synced 2025-12-21 20:07:06 +00:00
frontend: workaround musl getopt_long_only() bug,
see - https://www.openwall.com/lists/musl/2025/12/19/1
This commit is contained in:
@@ -2114,7 +2114,10 @@ int main(int argc, char **argv) {
|
|||||||
cpy_str(my_symbol->bgcolour, ARRAY_SIZE(my_symbol->bgcolour), "000000");
|
cpy_str(my_symbol->bgcolour, ARRAY_SIZE(my_symbol->bgcolour), "000000");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '?':
|
case '?': {
|
||||||
|
/* Workaround musl `optind` bug - see https://www.openwall.com/lists/musl/2025/12/19/1 */
|
||||||
|
const int idx = optind <= argc ? optind - 1 : argc - 1;
|
||||||
|
const char *const arg = argv[idx] ? argv[idx] : "?";
|
||||||
if (optopt) {
|
if (optopt) {
|
||||||
for (i = 0; i < ARRAY_SIZE(long_options) && long_options[i].val != optopt; i++);
|
for (i = 0; i < ARRAY_SIZE(long_options) && long_options[i].val != optopt; i++);
|
||||||
if (i == ARRAY_SIZE(long_options)) { /* Shouldn't happen */
|
if (i == ARRAY_SIZE(long_options)) { /* Shouldn't happen */
|
||||||
@@ -2122,15 +2125,15 @@ int main(int argc, char **argv) {
|
|||||||
return do_exit(ZINT_ERROR_ENCODING_PROBLEM);
|
return do_exit(ZINT_ERROR_ENCODING_PROBLEM);
|
||||||
}
|
}
|
||||||
if (long_options[i].has_arg) {
|
if (long_options[i].has_arg) {
|
||||||
fprintf(stderr, "Error 109: option '%s' requires an argument\n", argv[optind - 1]);
|
fprintf(stderr, "Error 109: option '%s' requires an argument\n", arg);
|
||||||
} else {
|
} else {
|
||||||
const char *eqs = strchr(argv[optind - 1], '=');
|
const char *const eqs = strchr(arg, '=');
|
||||||
const int optlen = eqs ? (int) (eqs - argv[optind - 1]) : (int) strlen(argv[optind - 1]);
|
const int optlen = eqs ? (int) (eqs - arg) : (int) strlen(arg);
|
||||||
fprintf(stderr, "Error 126: option '%.*s' does not take an argument\n", optlen,
|
fprintf(stderr, "Error 126: option '%.*s' does not take an argument\n", optlen, arg);
|
||||||
argv[optind - 1]);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Error 101: unknown option '%s'\n", argv[optind - 1]);
|
fprintf(stderr, "Error 101: unknown option '%s'\n", arg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return do_exit(ZINT_ERROR_INVALID_OPTION);
|
return do_exit(ZINT_ERROR_INVALID_OPTION);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1390,6 +1390,64 @@ static void test_exit_status(const testCtx *const p_ctx) {
|
|||||||
testFinish();
|
testFinish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_bad_args(const testCtx *const p_ctx) {
|
||||||
|
int debug = p_ctx->debug;
|
||||||
|
|
||||||
|
struct item {
|
||||||
|
int b;
|
||||||
|
const char *data;
|
||||||
|
int input_mode;
|
||||||
|
const char *opt;
|
||||||
|
const char *opt_data;
|
||||||
|
|
||||||
|
const char *expected;
|
||||||
|
};
|
||||||
|
/* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */
|
||||||
|
struct item data[] = {
|
||||||
|
/* 0*/ { BARCODE_CODE128, NULL, -1, NULL, NULL, "Error 109: option '-d' requires an argument" },
|
||||||
|
/* 1*/ { BARCODE_CODE128, "1", -1, " -o", NULL, "Error 109: option '-o' requires an argument" },
|
||||||
|
/* 2*/ { BARCODE_CODE128, "1", -1, " --fast=", "1", "Error 126: option '--fast' does not take an argument" },
|
||||||
|
};
|
||||||
|
int data_size = ARRAY_SIZE(data);
|
||||||
|
int i;
|
||||||
|
int exit_status;
|
||||||
|
|
||||||
|
char cmd[4096];
|
||||||
|
char buf[8192];
|
||||||
|
|
||||||
|
testStart("test_bad_args");
|
||||||
|
|
||||||
|
for (i = 0; i < data_size; i++) {
|
||||||
|
|
||||||
|
if (testContinue(p_ctx, i)) continue;
|
||||||
|
|
||||||
|
strcpy(cmd, "zint");
|
||||||
|
*buf = '\0';
|
||||||
|
|
||||||
|
arg_int(cmd, "-b ", data[i].b);
|
||||||
|
arg_input_mode(cmd, data[i].input_mode);
|
||||||
|
if (data[i].data) {
|
||||||
|
arg_data(cmd, "-d ", data[i].data);
|
||||||
|
} else {
|
||||||
|
strcat(cmd, " -d");
|
||||||
|
}
|
||||||
|
if (data[i].opt) {
|
||||||
|
if (data[i].opt_data != NULL) {
|
||||||
|
arg_data(cmd, data[i].opt, data[i].opt_data);
|
||||||
|
} else {
|
||||||
|
strcat(cmd, data[i].opt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
strcat(cmd, " 2>&1");
|
||||||
|
|
||||||
|
assert_nonnull(exec(cmd, buf, sizeof(buf) - 1, debug, i, &exit_status), "i:%d exec(%s) NULL\n", i, cmd);
|
||||||
|
assert_zero(strcmp(buf, data[i].expected), "i:%d buf (%s) != expected (%s) (%s)\n", i, buf, data[i].expected, cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
testFinish();
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
testFunction funcs[] = { /* name, func */
|
testFunction funcs[] = { /* name, func */
|
||||||
@@ -1404,6 +1462,7 @@ int main(int argc, char *argv[]) {
|
|||||||
{ "test_other_opts", test_other_opts },
|
{ "test_other_opts", test_other_opts },
|
||||||
{ "test_combos", test_combos },
|
{ "test_combos", test_combos },
|
||||||
{ "test_exit_status", test_exit_status },
|
{ "test_exit_status", test_exit_status },
|
||||||
|
{ "test_bad_args", test_bad_args },
|
||||||
};
|
};
|
||||||
|
|
||||||
testRun(argc, argv, funcs, ARRAY_SIZE(funcs));
|
testRun(argc, argv, funcs, ARRAY_SIZE(funcs));
|
||||||
|
|||||||
Reference in New Issue
Block a user