opt: fix opt_unregister.
authorRusty Russell <rusty@rustcorp.com.au>
Tue, 11 Feb 2020 04:09:43 +0000 (14:39 +1030)
committerRusty Russell <rusty@rustcorp.com.au>
Tue, 11 Feb 2020 04:09:43 +0000 (14:39 +1030)
Instead of memmoving N structs, we were memmoving N bytes.

But why did the test pass then?  It was doing memmove(..., 1)
instead of memmove(..., sizeof(struct opt_table)!

Because the two structures were really similar; the main difference
was the first entry, which points to the name.  But they were allocated
consecutively, and Intel being little-endian, the only difference was
the first byte!  Thus memmove(1) was enough to make it "work".

Change two options in the test to be sufficiently different, and
the bug shows up.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ccan/opt/opt.c
ccan/opt/test/run-unregister.c

index d4601dfbb230a3076edfa64d8b5232996f4d59d2..d376a598da932445de592c8f12e2466d4bc431bd 100644 (file)
@@ -189,7 +189,8 @@ bool opt_unregister(const char *names)
        if (found == -1)
                return false;
        opt_count--;
-       memmove(&opt_table[found], &opt_table[found+1], opt_count - found);
+       memmove(&opt_table[found], &opt_table[found+1],
+               (opt_count - found) * sizeof(opt_table[found]));
        return true;
 }
 
index 06bf58a0ce36b71a7993a7b7cadad542c4998d2f..d2dc469bd03f274105cb34a27626efd0627f8fa2 100644 (file)
@@ -10,11 +10,10 @@ int main(int argc, char *argv[])
 {
        const char *myname = argv[0];
 
-       plan_tests(14);
+       plan_tests(15);
 
-       /* Simple short arg.*/
        opt_register_noarg("--aaa|-a", test_noarg, NULL, "AAAAAAll");
-       opt_register_noarg("-b", test_noarg, NULL, "AAAAAAll");
+       opt_register_arg("-b", test_arg, NULL, "bbb", "b");
 
        /* We can't unregister wrong ones, but can unregister correct one */
        ok1(!opt_unregister("--aaa"));
@@ -22,7 +21,7 @@ int main(int argc, char *argv[])
        ok1(opt_unregister("--aaa|-a"));
 
        /* Arg parsing works as if we'd never registered it */
-       ok1(parse_args(&argc, &argv, "-b", NULL));
+       ok1(parse_args(&argc, &argv, "-bbbb", NULL));
        ok1(argc == 1);
        ok1(argv[0] == myname);
        ok1(argv[1] == NULL);