[PATCH] cmake: workaround GCC 7.2 segfault on v?sn?printf

Alexander Turenko alexander.turenko at tarantool.org
Fri Dec 28 07:48:54 MSK 2018


GCC 7.2.1 fails like so on our codebase:

/tarantool/src/lib/json/json.c: In function ‘json_token_snprint’:
/tarantool/src/lib/json/json.c:324:1: internal compiler error: Segmentation fault
 json_token_snprint(char *buf, int size, const struct json_token *token,
 ^~~~~~~~~~~~~~~~~~

The backtrace of cc1 is the following (failed to install compatible
debuginfo on Fedora 26, so ??s):

    #0  0x0000000000d0320c in get_source_location_for_substring(cpp_reader*, string_concat_db*, unsigned int, cpp_ttype, int, int, int, unsigned int*) ()
    #1  0x00000000005c0e79 in c_get_substring_location(substring_loc const&, unsigned int*) ()
    #2  0x00000000007f8418 in format_warning_va(substring_loc const&, source_range const*, char const*, int, char const*, __va_list_tag (*) [1]) ()
    #3  0x00000000007f838b in format_warning_at_substring(substring_loc const&, source_range const*, char const*, int, char const*, ...) ()
    #4  0x0000000000c72c2d in ?? ()
    #5  0x0000000000f6f308 in execute_one_pass(opt_pass*) ()
    #6  0x0000000000787da6 in ?? ()
    #7  0x00000000012ac338 in symbol_table::compile() ()
    #8  0x0000000000de650f in symbol_table::finalize_compilation_unit() ()
    #9  0x00000000012ee8df in ?? ()
    #10 0x0000000000d3ba84 in toplev::main(int, char**) ()
    #11 0x0000000000d3d35b in main ()

The issue in the GCC bugtracker: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83448

The idea of the commit is to check builtin snprintf with the code from
GCC test suite and disable all related builtins if the compiler is GCC
and the case fails.

We also need to disable FORTIFY_SOURCES in the case, because it uses
v?sn?printf builtins directly.
---

no issue
https://github.com/tarantool/tarantool/tree/Totktonada/workaround-gcc-7.2-snprintf-segfault

Be attentive: I pushed DO NOT MERGE commit upward the commit I send here
to enable full testing on the bugfix branch: [1] (hope it will pass).
The topmost commit should NOT be pushed to 2.1.

[1]: https://travis-ci.org/tarantool/tarantool/builds/472881226

 cmake/compiler.cmake | 43 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/cmake/compiler.cmake b/cmake/compiler.cmake
index 4062d13ec..b471b0c38 100644
--- a/cmake/compiler.cmake
+++ b/cmake/compiler.cmake
@@ -333,6 +333,8 @@ if (NOT HAVE_BUILTIN_CTZ OR NOT HAVE_BUILTIN_CTZLL)
             HAVE_FFSL)
         check_c_source_compiles("#include <string.h>\n#include <strings.h>\nint main(void) { return ffsll(0UL); }"
             HAVE_FFSLL)
+        set(CMAKE_REQUIRED_FLAGS "")
+        set(CMAKE_REQUIRED_DEFINITIONS "")
     endif()
 endif()
 
@@ -343,3 +345,44 @@ else()
     set(CMAKE_HOST_C_COMPILER ${CMAKE_C_COMPILER})
     set(CMAKE_HOST_CXX_COMPILER ${CMAKE_CXX_COMPILER})
 endif()
+
+# Check for broken __builtin_v?sn?printf() in gcc-7.2.
+# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83448
+
+# It is important for the test case to be compiled w/o any extra
+# flags and with -O2. Say, -Wall allows the case be compiled
+# successfully on gcc-7.2.1.
+set(PREVIOUS_CMAKE_C_FLAGS ${CMAKE_C_FLAGS})
+set(CMAKE_C_FLAGS "")
+set(CMAKE_REQUIRED_DEFINITIONS "")
+set(CMAKE_REQUIRED_INCLUDES "")
+set(CMAKE_REQUIRED_LIBRARIES "")
+set(CMAKE_REQUIRED_FLAGS "-O2")
+
+check_c_source_compiles("
+char *a;
+int b;
+
+int
+main(void)
+{
+    for (;;) {
+        if (b < 0)
+            main();
+        __builtin_snprintf(a, b, \"%*s\", b, \"\");
+    }
+    return 0;
+}" HAVE_BUILTIN_SNPRINTF)
+
+set(CMAKE_REQUIRED_FLAGS "")
+set(CMAKE_C_FLAGS ${PREVIOUS_CMAKE_C_FLAGS})
+
+# /usr/include/stdio.h (bits/stdio2.h to be exact) uses builtin
+# gcc v?sn?printf functions when fortify source is enabled.
+if (CMAKE_COMPILER_IS_GNUCC AND NOT HAVE_BUILTIN_SNPRINTF)
+    add_compile_flags("C;CXX" "-Wp,-U_FORTIFY_SOURCE")
+    add_compile_flags("C;CXX" "-fno-builtin-sprintf")
+    add_compile_flags("C;CXX" "-fno-builtin-snprintf")
+    add_compile_flags("C;CXX" "-fno-builtin-vsnprintf")
+    add_compile_flags("C;CXX" "-fno-builtin-vsprintf")
+endif()
-- 
2.20.1




More information about the Tarantool-patches mailing list