• Bug#1109256: libkpathsea-dev: redeclares Standard C functions with inco

    From Simon McVittie@21:1/5 to All on Mon Jul 14 11:10:01 2025
    Package: libkpathsea-dev
    Version: 2024.20240313.70630+ds-6
    Severity: important
    Tags: ftbfs upstream forky sid
    Control: block 1096597 by -1
    Control: affects -1 + src:evince

    In #1096597, Matthias Klose reported that evince FTBFS with gcc-15 as
    default (it is not the default for trixie, but will become the default
    in forky). This seems to be caused by libkpathsea-dev's headers,
    combined with gcc-15 defaulting to C23.

    As an example of the class of issue I'm reporting, libkpathsea-dev's
    c-std.h has this:

    #ifdef HAVE_STDLIB_H
    #include <stdlib.h>
    /* Include <stdlib.h> before <stddef.h>, to help avoid NULL
    redefinitions on some systems. (We don't include <stddef.h>
    ourselves any more, but FYI.) */
    #else
    /* It's impossible to say for sure what the system will deign to put in
    <stdlib.h>, but let's hope it's at least this. */
    extern char *getenv ();
    #endif /* not HAVE_STDLIB_H */

    and evince includes <stdlib.h> followed by <kpathsea/c-std.h>.

    The code in c-std.h assumes that the build system of every dependent
    package will check for stdlib.h and define HAVE_STDLIB_H if found, but
    there is a tendency to stop doing that, and instead assume that all
    platforms comply with a 1989 C standard by now. In particular Evince
    does not check for <stdlib.h>, and includes it unconditionally (I
    assume).

    In C11 or older, `extern char *getenv ()` declares getenv() as a
    function taking unspecified parameters and returning a string, but in
    C23 it declares getenv() as a function taking *no* parameters and
    returning a string, hence the compiler sees this as a declaration that
    is incompatible with the one it already saw in <stdlib.h>, and errors
    out:

    /usr/include/kpathsea/c-std.h:48:14: error: conflicting types for ‘getenv’; have ‘char *(void)’
    48 | extern char *getenv ();
    | ^~~~~~

    An equivalent failure mode is seen in the evince build log for other
    Standard C functions like strtok() and strstr(). There might be others,
    I didn't inspect all of the kpathsea headers.

    evince could presumably work around this by conditionally or
    unconditionally defining HAVE_STDLIB_H, etc., before it includes
    kpathsea headers; but it shouldn't have to, because each library should
    be self-contained.

    I think <kpathsea/c-std.h> should do something more like this
    (pseudo-patch, untested) so that it treats __STDC__ as implying that
    every Standard C header is present:

    -#ifdef HAVE_STDLIB_H
    +#if defined(__STDC__) || defined(HAVE_STDLIB_H)
    #include <stdlib.h>
    ...

    (or it could check __STDC_VERSION__ if preferred)

    ... or it could just assume that every platform has Standard C headers
    by now, since C89 is several decades old.

    Thanks,
    smcv

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Norbert Preining@21:1/5 to Simon McVittie on Mon Jul 14 16:30:01 2025
    AFAIR one needs to pass
    -std=gnu17
    which should suffice.

    Best regards

    Norbert

    On Mon, 14 Jul 2025, Simon McVittie wrote:
    Package: libkpathsea-dev
    Version: 2024.20240313.70630+ds-6
    Severity: important
    Tags: ftbfs upstream forky sid
    Control: block 1096597 by -1
    Control: affects -1 + src:evince

    In #1096597, Matthias Klose reported that evince FTBFS with gcc-15 as
    default (it is not the default for trixie, but will become the default
    in forky). This seems to be caused by libkpathsea-dev's headers,
    combined with gcc-15 defaulting to C23.

    As an example of the class of issue I'm reporting, libkpathsea-dev's
    c-std.h has this:

    #ifdef HAVE_STDLIB_H
    #include <stdlib.h>
    /* Include <stdlib.h> before <stddef.h>, to help avoid NULL
    redefinitions on some systems. (We don't include <stddef.h>
    ourselves any more, but FYI.) */
    #else
    /* It's impossible to say for sure what the system will deign to put in
    <stdlib.h>, but let's hope it's at least this. */
    extern char *getenv ();
    #endif /* not HAVE_STDLIB_H */

    and evince includes <stdlib.h> followed by <kpathsea/c-std.h>.

    The code in c-std.h assumes that the build system of every dependent
    package will check for stdlib.h and define HAVE_STDLIB_H if found, but
    there is a tendency to stop doing that, and instead assume that all
    platforms comply with a 1989 C standard by now. In particular Evince
    does not check for <stdlib.h>, and includes it unconditionally (I
    assume).

    In C11 or older, `extern char *getenv ()` declares getenv() as a
    function taking unspecified parameters and returning a string, but in
    C23 it declares getenv() as a function taking *no* parameters and
    returning a string, hence the compiler sees this as a declaration that
    is incompatible with the one it already saw in <stdlib.h>, and errors
    out:

    /usr/include/kpathsea/c-std.h:48:14: error: conflicting types for ‘getenv’; have ‘char *(void)’
    48 | extern char *getenv ();
    | ^~~~~~

    An equivalent failure mode is seen in the evince build log for other
    Standard C functions like strtok() and strstr(). There might be others,
    I didn't inspect all of the kpathsea headers.

    evince could presumably work around this by conditionally or
    unconditionally defining HAVE_STDLIB_H, etc., before it includes
    kpathsea headers; but it shouldn't have to, because each library should
    be self-contained.

    I think <kpathsea/c-std.h> should do something more like this
    (pseudo-patch, untested) so that it treats __STDC__ as implying that
    every Standard C header is present:

    -#ifdef HAVE_STDLIB_H
    +#if defined(__STDC__) || defined(HAVE_STDLIB_H)
    #include <stdlib.h>
    ...

    (or it could check __STDC_VERSION__ if preferred)

    ... or it could just assume that every platform has Standard C headers
    by now, since C89 is several decades old.

    Thanks,
    smcv


    --
    DI Dr Norbert Preining https://www.preining.info
    arXiv / Cornell University + IFMGA Guide + TU Wien + TeX Live
    GPG: 0x860CDC13 fp: F7D8 A928 26E3 16A1 9FA0 ACF0 6CAC A448 860C DC13

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Simon McVittie@21:1/5 to Norbert Preining on Mon Jul 14 17:30:01 2025
    On Mon, 14 Jul 2025 at 23:10:21 +0900, Norbert Preining wrote:
    AFAIR one needs to pass
    -std=gnu17
    which should suffice.

    I think that would be another viable workaround, but ideally dependent
    packages like evince shouldn't need to know and hard-code "my
    dependencies aren't C23-compatible" because that scales pretty badly, so
    I'd prefer to leave this bug open. (For forky - like the original FTBFS
    report, I'm certainly not asking for anything to change here for
    trixie!)

    I suspect this could also be an issue if anything is using libkpathsea
    from C++ code, which has the C23-like interpretation of the meaning of a declaration with no arguments.

    smcv

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)