dtc icon indicating copy to clipboard operation
dtc copied to clipboard

Two units tests fails on FreeBSD 14.2-RELEASE (amd64) with version 1.7.2

Open diizzyy opened this issue 7 months ago • 2 comments

Project version: 1.7.2
C compiler for the host machine: cc (clang 18.1.6 "FreeBSD clang version 18.1.6 (https://github.com/llvm/llvm-project.git llvmorg-18.1.6-0-g1118c2e05e67)")
C linker for the host machine: cc ld.lld 18.1.6

>>> MSAN_OPTIONS=halt_on_error=1:abort_on_error=1:print_summary=1:print_stacktrace=1 MESON_TEST_ITERATION=1 UBSAN_OPTIONS=halt_on_error=1:abort_on_error=1:print_summary=1:print_stacktrace=1 NO_YAML=0 MALLOC_PERTURB_=186 ASAN_OPTIONS=halt_on_error=1:abort_on_error=1:print_summary=1 NO_PYTHON=1 LD_LIBRARY_PATH=/usr/ports/sysutils/dtc/work/dtc-1.7.2/_build/libfdt /usr/ports/sysutils/dtc/work/dtc-1.7.2/tests/run_tests.sh -t fdtget

fdtget-runtest.sh "MyBoardName\0MyBoardFamilyName\0" -tr label01.dts.fdtget.test.dtb / compatible:      FAIL Results differ from expected

>>> MSAN_OPTIONS=halt_on_error=1:abort_on_error=1:print_summary=1:print_stacktrace=1 MESON_TEST_ITERATION=1 UBSAN_OPTIONS=halt_on_error=1:abort_on_error=1:print_summary=1:print_stacktrace=1 MALLOC_PERTURB_=34 NO_YAML=0 ASAN_OPTIONS=halt_on_error=1:abort_on_error=1:print_summary=1 NO_PYTHON=1 LD_LIBRARY_PATH=/usr/ports/sysutils/dtc/work/dtc-1.7.2/_build/libfdt /usr/ports/sysutils/dtc/work/dtc-1.7.2/tests/run_tests.sh -t fdtput

fdtput-runtest.sh 2 3 12 label01.dts.fdtput.test.dtb /randomnode tricky1 -tbi 02 003 12:        FAIL Results differ from expected

Using meson build without python support enabled

Let me know if you need more information

diizzyy avatar May 18 '25 07:05 diizzyy

That's unfortunate. However, I don't have easy access to a FreeBSD machine to debug with.

dgibson avatar May 21 '25 05:05 dgibson

Is there anything I can provide in terms of logs that may help etc?

diizzyy avatar Jun 07 '25 13:06 diizzyy

Is there anything I can provide in terms of logs that may help etc?

Not really, sorry. If you had good instructions for setting up a FreeBSD VM running on qemu on Linux, that would help.

dgibson avatar Jul 15 '25 02:07 dgibson

Ok, I figured out to get a FreeBSD VM running and I've diagnosed the problem.

The problem is that FreeBSD's printf(1) doesn't handle \0 escapes in parameters formatted with %b - it effectively terminates that argument. It's debatable whether that's a bug in printf - it does seem to be an inconsistency, because it will handle \0 in the main format string fine.

Still looking at how to fix / workaround this in the test.

dgibson avatar Jul 25 '25 01:07 dgibson

Well, that explains the first failure. The second one is different - it happens because on FreeBSD sscanf("003", "%i", &val) gives 0 rather than 3. In figuring out how to work around that, though, I discovered that a bunch of code in fdtput is pretty awful. Still looking at how to fix it.

dgibson avatar Jul 25 '25 03:07 dgibson

Ok, I figured out to get a FreeBSD VM running and I've diagnosed the problem.

The problem is that FreeBSD's printf(1) doesn't handle \0 escapes in parameters formatted with %b - it effectively terminates that argument. It's debatable whether that's a bug in printf - it does seem to be an inconsistency, because it will handle \0 in the main format string fine.

Still looking at how to fix / workaround this in the test.

No need to debate, FreeBSD's printf(1) manual page acknowledges this bug in the BUGS section. -> https://man.freebsd.org/cgi/man.cgi?query=printf&apropos=0&sektion=1&manpath=FreeBSD+14.2-RELEASE&arch=default&format=html#end

Workarounds:

  • install GNU coreutils and use the gprintf program, which works across \0
  • install bash and use its printf built-in, which works across \0

For FreeBSD, the former could use BINARY_ALIAS in ports unless the tests override/hardcode PATH.

mandree avatar Jul 25 '25 18:07 mandree

Well, that explains the first failure. The second one is different - it happens because on FreeBSD sscanf("003", "%i", &val) gives 0 rather than 3. In figuring out how to work around that, though, I discovered that a bunch of code in fdtput is pretty awful. Still looking at how to fix it.

Seems FreeBSD's sscanf is broken, but strtol seems OK.

// this is try.c
// compile and run: cc -o try try.c && ./try
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

int main() {
    int val;
    int len;
    int retval;
    retval = sscanf("003", "%i%n", &val, &len);
    printf("sscanf, retval = %d, val = %d, len = %d\n", retval, val, len);
    long longval;
    char *startptr = "003";
    char *endptr;
    errno = 0;
    longval = strtol(startptr, &endptr, 0);
    printf("strtol, longval = %ld, len = %d, errno = %d\n", longval, (int)(endptr - startptr), errno);
    return 0;
}

yields

sscanf, retval = 1, val = 0, len = 2
strtol, longval = 3, len = 3, errno = 0

Meaning sscanf chickened out in the middle of the "003" sequence, len is 2, but it claims 1 successful conversion in the return value. (0 is the octal specifier, 03 is an octal sequence that strtol can parse). POSIX suggests that sscanf's %i is supposed to scan "AS IF" strtol with base 0 were used.

https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=288440

mandree avatar Jul 25 '25 18:07 mandree

Ok, I figured out to get a FreeBSD VM running and I've diagnosed the problem. The problem is that FreeBSD's printf(1) doesn't handle \0 escapes in parameters formatted with %b - it effectively terminates that argument. It's debatable whether that's a bug in printf - it does seem to be an inconsistency, because it will handle \0 in the main format string fine. Still looking at how to fix / workaround this in the test.

No need to debate, FreeBSD's printf(1) manual page acknowledges this bug in the BUGS section. -> https://man.freebsd.org/cgi/man.cgi?query=printf&apropos=0&sektion=1&manpath=FreeBSD+14.2-RELEASE&arch=default&format=html#end

Ah, good to know.

Workarounds:

* install GNU coreutils and use the `gprintf` program, which works across `\0`

* install bash and use its `printf` **built-in**, which works across `\0`

For FreeBSD, the former could use BINARY_ALIAS in ports unless the tests override/hardcode PATH.

Turns out to be easier than that. BSD's printf(1) does handle \0 in the main format string. So we can just change the test script to use that rather than %b. Kind of not best practice, but not really a problem for our situation. I have a queued fix for this (see here).

dgibson avatar Jul 27 '25 05:07 dgibson

Well, that explains the first failure. The second one is different - it happens because on FreeBSD sscanf("003", "%i", &val) gives 0 rather than 3. In figuring out how to work around that, though, I discovered that a bunch of code in fdtput is pretty awful. Still looking at how to fix it.

Seems FreeBSD's sscanf is broken, but strtol seems OK.

Yes, I noticed that too. My plan is to switch to strtol() - I always find scanf() confusing anyway. I was sidetracked by spotting other nonsense in the surrounding code.

// this is try.c // compile and run: cc -o try try.c && ./try #include <stdlib.h> #include <stdio.h> #include <errno.h>

int main() { int val; int len; int retval; retval = sscanf("003", "%i%n", &val, &len); printf("sscanf, retval = %d, val = %d, len = %d\n", retval, val, len); long longval; char *startptr = "003"; char *endptr; errno = 0; longval = strtol(startptr, &endptr, 0); printf("strtol, longval = %ld, len = %d, errno = %d\n", longval, (int)(endptr - startptr), errno); return 0; }

yields

sscanf, retval = 1, val = 0, len = 2
strtol, longval = 3, len = 3, errno = 0

Meaning sscanf chickened out in the middle of the "003" sequence, len is 2, but it claims 1 successful conversion in the return value. (0 is the octal specifier, 03 is an octal sequence that strtol can parse). POSIX suggests that sscanf's %i is supposed to scan "AS IF" strtol with base 0 were used.

https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=288440

Ah, thanks. I signed up to get an account on the FreeBSD bugzilla, but you've saved me the trouble of filing this.

dgibson avatar Jul 27 '25 05:07 dgibson

Ok, punted on the other cleanups for the time being, but I believe I've fixed the bug on BSD. Can you please retry with latest git main.

dgibson avatar Jul 28 '25 06:07 dgibson

Checks out fine on 14.3-RELEASE (amd64) on my end, thanks!

diizzyy avatar Aug 02 '25 10:08 diizzyy

@diizzyy good to hear. Fwiw, I just got FreeBSD tests working again on Cirrus CI, so I hope to avoid this sort of regression in future.

dgibson avatar Aug 02 '25 10:08 dgibson