Skip to content

Fix teststr segfault when built with -ftrivial-auto-var-init#71

Closed
dimakuv wants to merge 1 commit intoapache:trunkfrom
dimakuv:dimakuv/fix-teststr-broken-case
Closed

Fix teststr segfault when built with -ftrivial-auto-var-init#71
dimakuv wants to merge 1 commit intoapache:trunkfrom
dimakuv:dimakuv/fix-teststr-broken-case

Conversation

@dimakuv
Copy link
Copy Markdown

@dimakuv dimakuv commented Mar 27, 2026

The apr test suite has a test error (segfault) when built with -ftrivial-auto-var-init=zero:

$ ./testall -v -q
testatomic : SUCCESS
testdir : SUCCESS
...
teststr             :  Segmentation fault

Debug stack trace:

(gdb) bt
#0 apr_strtok (str=str@entry=0x0, sep=sep@entry=0x43a429 " \t", last=last@entry=0x7fffffffe2d8) at strings/apr_strtok.c:35
#1 test_strtok (tc=0x7fffffffe380, data=<optimized out>) at test/teststr.c:81

Root cause analysis:

  • NULL, /* but who cares if apr_strtok() segfaults? */
  • retval1 = apr_strtok(str1, cases[curtc].sep, &state);
  • The apr_strtok(str, sep, internal_state) function must not be called with str == NULL in the first invocation. However the test does exactly this, and this leads to an access to *internal_state, which is technically undefined (uninitialized pointer on the stack).
  • Without -ftrivial-auto-var-init=zero, the *internal_state is benign by accident: the previous test case left the pointer-on-stack with some reasonable address. However, with -ftrivial-auto-var-init=zero, the *internal_state access fails because internal_state = NULL (auto-initialized to zero). So the whole test segfaults.

Reproducer

docker run -it amazonlinux:2023 /bin/bash

dnf install -y git vim make gcc14 autoconf libtool expat-devel
export CC=gcc14-gcc
export CFLAGS="$CFLAGS -ftrivial-auto-var-init=zero"

./buildconf
./configure
make -j
make test  # fails

cd test && ./testall -v -q  # to see the failure more clearly

Note that -ftrivial-auto-var-init=zero flag was introduced in GCC v12.

Testing the fix

$ cd test && ./testall -v -q
...
testsockopt         :  SUCCESS
teststr             :  SUCCESS  # <-- works now!
teststrnatcmp       :  SUCCESS
...

@notroj
Copy link
Copy Markdown
Contributor

notroj commented Mar 27, 2026

@dimakuv could you try adding another CI workflow to cover this compilation mode?

@dimakuv
Copy link
Copy Markdown
Author

dimakuv commented Mar 30, 2026

@notroj Looking at the current CI workflow (Linux example), I see that there are two knobs that the apr project uses:

  1. "config", e.g. config: --enable-maintainer-mode
  2. "notest-cflags", e.g. notest-cflags: -Werror

I cannot use the first knob, because there's no way to specify arbitrary compilation flags as inputs to the configure script (at least I don't see a way after inspecting ./configure --help).

I also cannot use the second knob (notest-cflags) because my PR fixes the test, and this knob applies only to non-test compilation units.

So the only option I see is to introduce a new variable cflags (similar to notest-cflags). This variable will be empty/undefined in all current workflows, and will be defined only in my new workflow. Smth like this:

diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
@@ -87,10 +87,14 @@ jobs:
             notest-cflags: -Werror
             config: --enable-maintainer-mode --with-berkeley-db --with-dbm=db5
             config-output: APU_HAVE_DB
+          - name: Auto-var-init
+            os: ubuntu-latest  # requires gcc 12 or higher
+            cflags: -ftrivial-auto-var-init=zero
       fail-fast: false

     runs-on: ${{ matrix.os }}
     env:
+      CFLAGS: ${{ matrix.cflags }}
       NOTEST_CFLAGS: ${{ matrix.notest-cflags }}
     name: ${{ matrix.name }}
     steps:

Is the above what you would recommend to add?

@notroj
Copy link
Copy Markdown
Contributor

notroj commented Mar 30, 2026

because my PR fixes the test, and this knob applies only to non-test compilation units

NOTEST_CFLAGS specifies flags which aren't used during the configure run, they are used for all compilation including in test/

* test/teststr.c -- one test case was broken and worked by accident: the
apr_strtok() function was intentionally called with `str == NULL` on
first invocation. This leads to an access to `*internal_state`, which is
technically undefined (uninitialized pointer on the stack).

Without `-ftrivial-auto-var-init`, the `*internal_state` is benign by
accident: the previous test case left the pointer-on-stack with some
reasonable address. However, with `-ftrivial-auto-var-init=zero`, the
`*internal_state` access fails because `internal_state = NULL`
(auto-initialized to zero). So the whole test segfaults.

This commit comments out this broken test case and also adds a new CI
workflow to cover this `-ftrivial-auto-var-init` compilation mode.
@dimakuv dimakuv force-pushed the dimakuv/fix-teststr-broken-case branch from 54ae6d1 to e242c3b Compare March 30, 2026 09:10
@dimakuv
Copy link
Copy Markdown
Author

dimakuv commented Mar 30, 2026

because my PR fixes the test, and this knob applies only to non-test compilation units

NOTEST_CFLAGS specifies flags which aren't used during the configure run, they are used for all compilation including in test/

Thanks, I didn't realize this (the name misled me, and I incorrectly read the comments about this envvar the first time).

Fixed now.

@notroj
Copy link
Copy Markdown
Contributor

notroj commented Mar 30, 2026

Perfect, thanks a lot!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants