Skip to content

Audit: portability & correctness bugs (hardcoded paths, CMake, BigInt, isIncomplete, version detection) #4

Description

@sergiorandria

Summary

Automated audit found multiple portability, correctness and maintainability bugs that should be fixed before enabling branch protection / release. Most are triggered on CI (ubuntu-24.04, LLVM 22 apt.llvm.org) or on a fresh clone away from /home/sergio.

1. CMakeLists.txt:23,38 – hardcoded clang-cpp / LLVM search – CI failure 🔴

Location: CMakeLists.txt:23 find_library(CLANG_CPP_LIB clang-cpp HINTS /usr/lib) and :38 find_library(LLVM_SINGLE_LIB LLVM-22 HINTS /usr/lib /usr/lib/llvm)

Evidence:

  • CI log: Found LLVM 22.1.8 at /usr/lib/llvm-22/lib/cmake/llvmCMake Error at CMakeLists.txt:25 (message): clang-cpp not found
  • libclang-cpp22-dev on apt.llvm.org/noble installs:
    /usr/lib/llvm-22/lib/libclang-cpp.so -> libclang-cpp.so.22.1
    /usr/lib/x86_64-linux-gnu/libclang-cpp.so.22.1 (versioned)
    /usr/lib/x86_64-linux-gnu/libclang-cpp22.so (dev)
    
    Unversioned libclang-cpp.so only exists at /usr/lib/llvm-22/lib, not in default system search. Similarly libLLVM-22.so lives at /usr/lib/llvm-22/lib/libLLVM-22.so.
  • Arch layout (/usr/lib/libclang-cpp.so, /usr/include) works locally, so bug only visible on CI.

Expected: Support both layouts:

find_library(CLANG_CPP_LIB NAMES clang-cpp clang-cpp-22
  HINTS /usr/lib /usr/lib/x86_64-linux-gnu /usr/lib/llvm-22/lib ${LLVM_LIBRARY_DIRS} ${LLVM_DIR}/../..)
find_path(CLANG_INCLUDE_DIRS NAMES clang/Basic/Version.h
  HINTS /usr/include /usr/lib/llvm-22/include ${LLVM_INCLUDE_DIRS})
find_library(LLVM_SINGLE_LIB NAMES LLVM-22 LLVM
  HINTS /usr/lib /usr/lib/x86_64-linux-gnu /usr/lib/llvm-22/lib ${LLVM_LIBRARY_DIRS})

2. src/interpreter/interpreter.cpp:54,57 – hardcoded absolute paths 🔴

compilerArgsStorage_.push_back("/usr/lib/clang/22");
compilerArgsStorage_.push_back("/home/sergio/Project/cpp-repl/include");
  • /usr/lib/clang/22 is the Arch path. On Ubuntu the resource dir is /usr/lib/llvm-22/lib/clang/22 or discovered via clang::CompilerInstance/llvm-config --prefix. Hardcoding breaks CI and any other install prefix.
  • /home/sergio/Project/cpp-repl/include makes a fresh git clone elsewhere fail to find cpp-repl/fix_np_headers.hpp (force-included at :59). Repro: clone to /tmp, build – builtin headers break. Should be derived from PROJECT_SOURCE_DIR/CMAKE_CURRENT_SOURCE_DIR or installed prefix, or via target_include_directories.

Same issue in src/repl.cpp:27-28 (legacy Repl):

std::vector<const char *> args = {"-std=c++17", "-O0", "-resource-dir", "/usr/lib/clang/22"};

3. Dead / non-portable Numpy-C-API hints 🔴

src/interpreter/interpreter.cpp:55,548,672,716 contains explanations and error hints referencing a local checkout:

Use -I /home/sergio/Project/Numpy-C-API/include and #include "np/np.hpp"
Try: cpp-repl -std=c++23 -I /home/sergio/Project/Numpy-C-API/include

These paths leak a developer's home dir into user-facing diagnostics and should be generic (/path/to/Numpy-C-API/include or just suggest -I <path>).

4. include/cpp-repl/fix_proxy.hpp:10 – unconditional external include 🔴

#include "np/detail/proxy.hpp"

If this header were ever force-included, it fails unless Numpy-C-API is installed. File is currently dead (only fix_np_headers.hpp is -included) but still presents maintenance risk and breaks clang-tidy/cppcheck if enabled. Either remove or guard with #if __has_include.

5. src/interpreter/interpreter.cpp:266-329preprocessBigIntLiterals regex incomplete (functional bug) 🟡

Repro:

./build/cpp-repl --no-interactive -e 'bigint g = 12345678901234567890123456789012345678901234567890;'
# In file included from <<< inputs >>>:1:
# error: integer literal is too large

Expected: auto-wrap to bigint("..."). The regex only handles bigint|cpp_int|... \s+ \w+ \s*=\s* DIGITS ; but fails for:

  • const bigint, constexpr, static qualifiers before type
  • multi-declaration or template types like const std::vector<cpp_int>, though less common
  • The local uncommitted diff already adds handling but still misses auto literals used as function args, e.g., foo(123456789...)
    Should expand to handle qualifiers and report correct type extraction, or better rely on boost::multiprecision::cpp_int's user-defined literal if available.

6. src/repl/session.cpp:20-36 and src/interpreter/interpreter.cpp:824-843 – naive isIncomplete 🟡

Counts {, (, [ without stripping strings/comments. Example:

cpp> std::string s = "{";
...>

incorrectly considered incomplete (open brace in string). Python REPL correctly handles this via tokenization. Should reuse stripCommentsAndStrings logic from VersionDetector or use clang lexing.

7. src/interpreter/interpreter.cpp:233-257,162-179reinitWithCurrentOptions/ensureVersion replays history unsafely 🟡

  • reinitWithCurrentOptions and ensureVersion clear variables_/history_ then replay via eval(h, e) without handling re-entrancy: if replayed code triggers another ensureVersion upgrade, recursion could double-reinit.
  • variables_ tracking via regex parseDeclaration is lossy (misses std::string, templates, auto, etc.) and can silently corrupt undo state. undo() rebuilds from history but skips failed parseDeclaration, leaving stale entries.

8. src/utils/version_detector.cpp:88-111 – overly broad version detection 🟡

detect checks stripped.find("import") via contains("import ") etc., causing false positives on variable names like int important = 0; → triggers C++23 upgrade. Same for export, format, source_location. Should use containsWord.

9. Hardcoded version string 🟡

src/cli/cli.cpp:126-127 and README.md hardcode LLVM 22.1.3 / clang 22.1.8. CI now uses 22.1.8 for both. Should query LLVM_VERSION_MAJOR/PACKAGE_VERSION at cmake time and embed via configure_file.

10. Build: CMakeLists.txt missing dynamic resource-dir / include handling & HAS_READLINE 🟠

  • No clang -print-resource-dir detection; should use execute_process(clang -print-resource-dir) or ClangConfig.
  • Latest main adds READLINE detection at bottom but interpreter doesn't use it consistently (history handling).

Repro steps

cmake -B build -G Ninja -DLLVM_DIR=/usr/lib/llvm-22/lib/cmake/llvm  # CI
# fails at clang-cpp not found before fix
./build/cpp-repl --no-interactive -e 'bigint g = 1234567890123456789012345678901234567890;'
# error: integer literal is too large
git clone elsewhere && cmake -B build && ./build/cpp-repl --no-interactive -e 'int x=1;'
# fails to find fix_np_headers.hpp due to hardcoded /home/sergio path

Suggested priority


Generated by local audit (grep, llvm-config, gh, smoke tests) on e6e94b7 + unstaged changes. Happy to PR the CMake fix above.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions