Menu

#154 builtin implementation of snprintf doesn't work

Feature Request
pending
nobody
None
5
2026-03-18
2021-03-25
No

When cross-compiling log4cpp, the detection of snprintf by the autotools macro does not work and by default assumes that snprintf is not available.
As a result it uses an internal implementation of snprintf, unfortunately, that's broken, and logs are not correctly formatted.

Her is a suggested fix for the cross compiling case. It assumes that snprintf is always available in this case, which may not be how you want to fix this:

diff --git a/m4/AC_FUNC_SNPRINTF.m4 b/m4/AC_FUNC_SNPRINTF.m4
index 08af521..e2bfc51 100644
--- a/m4/AC_FUNC_SNPRINTF.m4
+++ b/m4/AC_FUNC_SNPRINTF.m4
@@ -15,7 +15,7 @@ AC_DEFUN([AC_FUNC_SNPRINTF],
 [AC_TRY_RUN([#include <stdio.h>
 int main () { int l = snprintf(NULL,0,"%d",100); exit (!((3 <= l) || (-1 == l))); }
 ], ac_cv_func_snprintf=yes, ac_cv_func_snprintf=no,
-ac_cv_func_snprintf=no)])
+ac_cv_func_snprintf=yes)])
 if test $ac_cv_func_snprintf = yes; then
   AC_DEFINE(HAVE_SNPRINTF,,[define if the C library has snprintf])
 fi

Discussion

  • Alexander Perepelkin

    • status: open --> pending
     
  • Alexander Perepelkin

    @pulkomandy,

    Could you tell what environment causes mentioned failure?
    What are host and target archs, and what problem is observed there?
    Simply assuming that snprintf is always available might be leading to even more troubles.

     
  • Adrien Destugues

    Hello,

    This was cross-compiling from (if I remember correctly) Debian 11 x86_64, using Yocto to build an arm64 Linux system.
    It is not possible in this configuration for AC_TRY_RUN to actually run the code, as documented in autoconf manual:

    https://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.72/html_node/Runtime.html

    Avoid running test programs if possible, because this prevents people from configuring your package for cross-compiling.

    (AC_TRY_RUN is renamed to AC_RUN_IFELSE in current autoconf versions, but it does the same thing, and older version of the documentation had the same warning).

    I'm not sure why the check was set up in the way it is. Does it really need to detect broken implementations of snprintf that return an incorrect value, or could a compile only check be enough?

     
  • Alexander Perepelkin

    I'm not sure why the check was set up in the way it is. Does it really need to detect broken implementations of snprintf that return an incorrect value, or could a compile only check be enough?

    Here is an answer to why:
    https://www.gnu.org/software/autoconf/manual/autoconf-2.71/autoconf.html

    snprintf

    In C99 and later, if the output array isn’t big enough and if no other errors occur, snprintf and vsnprintf truncate the output and return the number of bytes that ought to have been produced. Some older systems return the truncated length (e.g., GNU C Library 2.0.x or IRIX 6.5), some a negative value (e.g., earlier GNU C Library versions), and some the buffer length without truncation (e.g., 32-bit Solaris 7). Also, some buggy older systems ignore the length and overrun the buffer (e.g., 64-bit Solaris 7).

    One possible (though still out-of-library) way to overcome that is to alter your build script. If you know for sure that target system for which you cross-compile actually provides valid snprintf, then:

    # run customized ./configure
    ac_cv_func_snprintf=yes ./configure
    

    As a result it uses an internal implementation of snprintf, unfortunately, that's broken, and logs are not correctly formatted.

    Internally shipped fallback is taken from http://www.ijs.si/software/snprintf/ which is not complete replacement for standard snprintf() function.
    Was it totally unusable? Perhaps there are some logs samples left.

     
  • Adrien Destugues

    Hello,

    Unfortunately we didn't keep many more details about the problem, and I don't remember. If I read our internal ticket from back then correctly, logs using the %d format specifier were truncated too early, despite having sufficient space in the output buffer for snprintf (maybe only with "large" numbers).

    Since then, the project has switched to another logging library. So I'm not even able to easily do a build with unpatched log4cpp to check for the exact problem again.

     
  • Alexander Perepelkin

    logs using the %d format specifier were truncated too early

    Thanks, will keep in mind that there is an issue with implementation of internally shipped snprintf().

    As for cross-compilation for a specific target architecture and relying on the standard snprintf() implementation, I assume that running ./configure with preset variable as shown above is an appropriate solution.
    In common cross-compilation scenario, there is no reliable way to verify whether standard snprintf() runs correctly on the target platform when building solely on the host system.
    Therefore, assuming that standard snprintf() works as expected on any target architecture may be somewhat riskier than using a fallback, even though the fallback has limitations.

     

Log in to post a comment.

MongoDB Logo MongoDB