root-project / cling

The cling C++ interpreter

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

cling seems to segfault easily

Apteryks opened this issue · comments

Describe the bug

While experimenting with cling I found that I can have it segfault on demand with the recipe below.

Expected behavior

cling should not segfault itself.

To Reproduce

Steps to reproduce the behavior:

  1. launch cling with cling --std=c++17.
  2. input the following code:
#include <filesystem>
auto p = std::filesystem::path("/etc/pulse/client.conf");
auto cp = std::filesystem::canonical(p);
cp

The last line (an attempt to inspect cp), triggers a segfault for me (exit status 139 with error message "Segmentation fault").

Setup

  1. Cling version: 0.9-1.d78d1a0
  2. Operating system: Guix System
  3. How you obtained Cling: installed from Guix (commit ff14bc60e56fb0c6636da1da9a850b7b04abb367).

This is not a Cling issue per se. It's to do with std::filesystem::path usage and a mixup between the headers used and what's linked to your binary. Lots more info here:

I've seen the same thing. Perhaps Cling could make this easier to avoid.

The above links were very insightful, but I'm not using GCC 8 (I'm using a mixture of GCC 10.3.0 for the build and GCC 12.2.0 in my user profile (Guix).

The Guix package of cling reads as:

(define-public cling
  ;; The tagged v0.9 release doesn't build, so use the latest commit.
  (let ((commit "d78d1a03fedfd2bf6d2b6ff295aca576d98940df")
        (revision "1")
        (version* "0.9"))
    (package
      (name "cling")
      (version (git-version version* revision commit))
      (source (origin
                (method git-fetch)
                (uri (git-reference
                      (url "http://root.cern/git/cling.git")
                      (commit commit)))
                (file-name (git-file-name name version))
                (sha256
                 (base32
                  "0lsbxv21b4qw11xkw9iipdpca64jjwwqxm0qf5v2cgdlibf8m8n9"))
                ;; Patch submitted upstream here:
                ;; https://github.com/root-project/cling/pull/433.
                (patches (search-patches "cling-use-shared-library.patch"))))
      (build-system cmake-build-system)
      (arguments
       (list
        #:build-type "Release"          ;keep the build as lean as possible
        #:tests? #f                     ;FIXME: 78 tests fail (out of ~200)
        #:test-target "check-cling"
        #:configure-flags
        #~(list (string-append "-DCLING_CXX_PATH="
                               (search-input-file %build-inputs "bin/g++"))
                ;; XXX: The AddLLVM.cmake module expects LLVM_EXTERNAL_LIT to
                ;; be a Python script, not a shell executable.
                (string-append "-DLLVM_EXTERNAL_LIT="
                               (search-input-file %build-inputs "bin/.lit-real")))
        #:phases
        #~(modify-phases %standard-phases
            (add-after 'unpack 'set-version
              (lambda _
                (make-file-writable "VERSION")
                (call-with-output-file "VERSION"
                  (lambda (port)
                    (format port "~a~%" #$version)))))
            (add-after 'unpack 'patch-paths
              (lambda* (#:key inputs #:allow-other-keys)
                (substitute* "lib/Interpreter/CIFactory.cpp"
                  (("\bsed\b")
                   (which "sed"))
                  ;; This ensures that the default C++ library used by Cling is
                  ;; that of the compiler that was used to build it, rather
                  ;; than that of whatever g++ happens to be on PATH.
                  (("ReadCompilerIncludePaths\\(CLING_CXX_RLTV")
                   (format #f "ReadCompilerIncludePaths(~s"
                           (search-input-file inputs "bin/g++")))
                  ;; Cling uses libclang's CompilerInvocation::GetResourcesPath
                  ;; to resolve Clang's library prefix, but this fails on Guix
                  ;; because it is relative to the output of cling rather than
                  ;; clang (see:
                  ;; https://github.com/root-project/cling/issues/434).  Fully
                  ;; shortcut the logic in this method to return the correct
                  ;; static location.
                  (("static std::string getResourceDir.*" all)
                   (string-append all
                                  "    return std::string(\""
                                  #$(this-package-input "clang-cling")
                                  "/lib/clang/" #$(package-version clang-cling)
                                  "\");")))
                ;; Check for the 'lit' command for the tests, not 'lit.py'
                ;; (see: https://github.com/root-project/cling/issues/432).
                (substitute* "CMakeLists.txt"
                  (("lit.py")
                   "lit"))))
            (add-after 'unpack 'adjust-lit.cfg
              ;; See: https://github.com/root-project/cling/issues/435.
              (lambda _
                (substitute* "test/lit.cfg"
                  (("config.llvm_tools_dir \\+ '")
                   "config.cling_obj_root + '/bin"))))
            (add-after 'install 'delete-static-libraries
              ;; This reduces the size from 17 MiB to 5.4 MiB.
              (lambda _
                (for-each delete-file (find-files #$output "\\.a$")))))))
      (native-inputs
       (list python python-lit))
      (inputs
       (list clang-cling llvm-cling))
      (home-page "https://root.cern/cling/")
      (synopsis "Interactive C++ interpreter")
      (description "Cling is an interactive C++17 standard compliant
interpreter, built on top of LLVM and Clang.  Cling can be used as a
read-eval-print loop (REPL) to assist with rapid application development.
Here's how to print @samp{\"Hello World!\"} using @command{cling}:

@example
cling '#include <stdio.h>' 'printf(\"Hello World!\\n\");'
@end example")
      (license license:lgpl2.1+))))

Note the patching of the ReadCompilerIncludePaths(CLING_CXX_RLTV to use the g++ from the build environment rather than from the user's PATH. I'll try commenting this out to see if it improves things.

OK, I've done the experiment, and I now get:

$ /gnu/store/wkgf0f1605w5j4k39bma9w8y17j8nycb-cling-0.9-1.d78d1a0/bin/cling 

****************** CLING ******************
* Type C++ code and press enter to run it *
*             Type .q to exit             *
*******************************************
[cling]$ #include <filesystem>
[cling]$ auto p = std::filesystem::path("/etc/pulse/client.conf");
input_line_4:2:16: error: no member named 'filesystem' in namespace 'std'
 auto p = std::filesystem::path("/etc/pulse/client.conf");
          ~~~~~^
commented

OK, I've done the experiment, and I now get:

$ /gnu/store/wkgf0f1605w5j4k39bma9w8y17j8nycb-cling-0.9-1.d78d1a0/bin/cling 

****************** CLING ******************
* Type C++ code and press enter to run it *
*             Type .q to exit             *
*******************************************
[cling]$ #include <filesystem>
[cling]$ auto p = std::filesystem::path("/etc/pulse/client.conf");
input_line_4:2:16: error: no member named 'filesystem' in namespace 'std'
 auto p = std::filesystem::path("/etc/pulse/client.conf");
          ~~~~~^

std::filesystem was added in c++17 IIRC. cling defaults to c++11 IIRC. To use std::filesystem with cling, you need to start it as follows:

cling -std=c++17

I tried to run cling in a container; if I don't include a GCC toolchain with its headers it doesn't find the linux/errno.h header:

$ guix shell --container cling -- cling -std=c++17

****************** CLING ******************
* Type C++ code and press enter to run it *
*             Type .q to exit             *
*******************************************
[cling]$ 
[cling]$ #include <filesystem>
In file included from input_line_3:1:
In file included from /gnu/store/5lqhcv91ijy82p92ac6g5xw48l0lwwz4-gcc-11.3.0/include/c++/filesystem:44:
In file included from /gnu/store/5lqhcv91ijy82p92ac6g5xw48l0lwwz4-gcc-11.3.0/include/c++/bits/fs_fwd.h:35:
In file included from /gnu/store/5lqhcv91ijy82p92ac6g5xw48l0lwwz4-gcc-11.3.0/include/c++/system_error:39:
In file included from /gnu/store/5lqhcv91ijy82p92ac6g5xw48l0lwwz4-gcc-11.3.0/include/c++/x86_64-unknown-linux-gnu/bits/error_constants.h:34:
In file included from /gnu/store/5lqhcv91ijy82p92ac6g5xw48l0lwwz4-gcc-11.3.0/include/c++/cerrno:42:
In file included from /gnu/store/gsjczqir1wbz8p770zndrpw4rnppmxi3-glibc-2.35/include/errno.h:28:
/gnu/store/gsjczqir1wbz8p770zndrpw4rnppmxi3-glibc-2.35/include/bits/errno.h:26:11: fatal error: 'linux/errno.h' file not found
# include <linux/errno.h>
          ^~~~~~~~~~~~~~~

If I do, I still get a crash:

$ guix shell --container cling gcc-toolchain@11 -- cling -std=c++17
[...]
****************** CLING ******************
* Type C++ code and press enter to run it *
*             Type .q to exit             *
*******************************************
[cling]$ #include <filesystem>
[cling]$ std::filesystem::path("/etc/pulse/client.conf");
free(): invalid pointer
/gnu/store/havpcz2bgi5fd0fj52r7pgb4f73z465x-llvm-cling-9.0.1/lib/libLLVM-9.so(_ZN4llvm3sys15PrintStackTraceERNS_11raw_ostreamE+0x3b)[0x7f94506ce4bb]
/gnu/store/havpcz2bgi5fd0fj52r7pgb4f73z465x-llvm-cling-9.0.1/lib/libLLVM-9.so(_ZN4llvm3sys17RunSignalHandlersEv+0x34)[0x7f94506cc514]
/gnu/store/havpcz2bgi5fd0fj52r7pgb4f73z465x-llvm-cling-9.0.1/lib/libLLVM-9.so(+0x70f642)[0x7f94506cc642]
/gnu/store/gsjczqir1wbz8p770zndrpw4rnppmxi3-glibc-2.35/lib/libc.so.6(+0x3d2a0)[0x7f944faf22a0]
/gnu/store/gsjczqir1wbz8p770zndrpw4rnppmxi3-glibc-2.35/lib/libc.so.6(+0x86fec)[0x7f944fb3bfec]
/gnu/store/gsjczqir1wbz8p770zndrpw4rnppmxi3-glibc-2.35/lib/libc.so.6(raise+0x12)[0x7f944faf2202]
/gnu/store/gsjczqir1wbz8p770zndrpw4rnppmxi3-glibc-2.35/lib/libc.so.6(abort+0xc1)[0x7f944fadd45b]
/gnu/store/gsjczqir1wbz8p770zndrpw4rnppmxi3-glibc-2.35/lib/libc.so.6(__libc_fatal+0x0)[0x7f944fb30990]
/gnu/store/gsjczqir1wbz8p770zndrpw4rnppmxi3-glibc-2.35/lib/libc.so.6(+0x904ba)[0x7f944fb454ba]
/gnu/store/gsjczqir1wbz8p770zndrpw4rnppmxi3-glibc-2.35/lib/libc.so.6(+0x91fcc)[0x7f944fb46fcc]
/gnu/store/gsjczqir1wbz8p770zndrpw4rnppmxi3-glibc-2.35/lib/libc.so.6(free+0x6f)[0x7f944fb49b3f]
/gnu/store/930nwsiysdvy2x5zv1sf6v7ym75z8ayk-gcc-11.3.0-lib/lib/libstdc++.so.6(_ZNKSt10filesystem7__cxx114path5_List13_Impl_deleterclEPNS2_5_ImplE+0x4a)[0x7f944ff1e44a]
[0x7f944f995482]
[0x7f944f9953fc]
[0x7f944f99516c]
[0x7f944f99513c]
[0x7f944f99534d]
[0x7f944f99530c]
[0x7f944f99503b]
cling(_ZNK5cling19IncrementalExecutor14executeWrapperEN4llvm9StringRefEPNS_5ValueE+0x30c)[0x51057c]
Stack dump:
0.      Program arguments: cling -std=c++17 
maxim@hurd ~$ guix shell --container cling gcc-toolchain@11 -- cling -std=c++17

****************** CLING ******************
* Type C++ code and press enter to run it *
*             Type .q to exit             *
*******************************************
[cling]$ std::filesystem::path("/");
input_line_3:2:7: error: no member named 'filesystem' in namespace 'std'
 std::filesystem::path("/");
 ~~~~~^
[cling]$ #include <filesystem>
^[[A[cling]$ std::filesystem::path("/");
free(): invalid pointer
/gnu/store/havpcz2bgi5fd0fj52r7pgb4f73z465x-llvm-cling-9.0.1/lib/libLLVM-9.so(_ZN4llvm3sys15PrintStackTraceERNS_11raw_ostreamE+0x3b)[0x7fe53f9064bb]
/gnu/store/havpcz2bgi5fd0fj52r7pgb4f73z465x-llvm-cling-9.0.1/lib/libLLVM-9.so(_ZN4llvm3sys17RunSignalHandlersEv+0x34)[0x7fe53f904514]
/gnu/store/havpcz2bgi5fd0fj52r7pgb4f73z465x-llvm-cling-9.0.1/lib/libLLVM-9.so(+0x70f642)[0x7fe53f904642]
/gnu/store/gsjczqir1wbz8p770zndrpw4rnppmxi3-glibc-2.35/lib/libc.so.6(+0x3d2a0)[0x7fe53ed2a2a0]
/gnu/store/gsjczqir1wbz8p770zndrpw4rnppmxi3-glibc-2.35/lib/libc.so.6(+0x86fec)[0x7fe53ed73fec]
/gnu/store/gsjczqir1wbz8p770zndrpw4rnppmxi3-glibc-2.35/lib/libc.so.6(raise+0x12)[0x7fe53ed2a202]
/gnu/store/gsjczqir1wbz8p770zndrpw4rnppmxi3-glibc-2.35/lib/libc.so.6(abort+0xc1)[0x7fe53ed1545b]
/gnu/store/gsjczqir1wbz8p770zndrpw4rnppmxi3-glibc-2.35/lib/libc.so.6(__libc_fatal+0x0)[0x7fe53ed68990]
/gnu/store/gsjczqir1wbz8p770zndrpw4rnppmxi3-glibc-2.35/lib/libc.so.6(+0x904ba)[0x7fe53ed7d4ba]
/gnu/store/gsjczqir1wbz8p770zndrpw4rnppmxi3-glibc-2.35/lib/libc.so.6(+0x91fcc)[0x7fe53ed7efcc]
/gnu/store/gsjczqir1wbz8p770zndrpw4rnppmxi3-glibc-2.35/lib/libc.so.6(free+0x6f)[0x7fe53ed81b3f]
/gnu/store/930nwsiysdvy2x5zv1sf6v7ym75z8ayk-gcc-11.3.0-lib/lib/libstdc++.so.6(_ZNKSt10filesystem7__cxx114path5_List13_Impl_deleterclEPNS2_5_ImplE+0x4a)[0x7fe53f15644a]
[0x7fe53ebcd482]
[0x7fe53ebcd3fc]
[0x7fe53ebcd16c]
[0x7fe53ebcd13c]
[0x7fe53ebcd34d]
[0x7fe53ebcd30c]
[0x7fe53ebcd03b]
cling(_ZNK5cling19IncrementalExecutor14executeWrapperEN4llvm9StringRefEPNS_5ValueE+0x30c)[0x51057c]
Stack dump:
0.      Program arguments: cling -std=c++17

The version of GCC used at build time (GCC 11) is the same provided in the container; but it seems there's a problem between LLVM 9 used by Cling and GCC 11 in my environment?

I retried with latest master, and I get:

(std::filesystem::path &) /etc/pulse/client.conf

Please retry on your side with that version and reopen if needed, thanks!

Seems to work fine as of cling v1.0. Thanks for checking!