Skip to content

Reject invalid integer constants in unevaluated preprocessor operands #134884

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 8, 2025

Conversation

AaronBallman
Copy link
Collaborator

Clang was previously accepting invalid code like:

  #if 1 ? 1 : 999999999999999999999
  #endif

because the integer constant (which is too large to fit into any standard or extended integer type) was in an unevaluated branch of the conditional operator. Similar invalid code involving || or && was also accepted and is now rejected.

Fixes #134658

Clang was previously accepting invalid code like:

  #if 1 ? 1 : 999999999999999999999
  #endif

because the integer constant (which is too large to fit into any
standard or extended integer type) was in an unevaluated branch of the
conditional operator. Similar invalid code involving || or && was also
accepted and is now rejected.

Fixes llvm#134658
@AaronBallman AaronBallman added clang Clang issues not falling into any other category c c++ clang:frontend Language frontend issues, e.g. anything involving "Sema" accepts-invalid labels Apr 8, 2025
@llvmbot
Copy link
Member

llvmbot commented Apr 8, 2025

@llvm/pr-subscribers-clang

Author: Aaron Ballman (AaronBallman)

Changes

Clang was previously accepting invalid code like:

  #if 1 ? 1 : 999999999999999999999
  #endif

because the integer constant (which is too large to fit into any standard or extended integer type) was in an unevaluated branch of the conditional operator. Similar invalid code involving || or && was also accepted and is now rejected.

Fixes #134658


Full diff: https://github.com/llvm/llvm-project/pull/134884.diff

3 Files Affected:

  • (modified) clang/docs/ReleaseNotes.rst (+8)
  • (modified) clang/lib/Lex/PPExpressions.cpp (+2-3)
  • (added) clang/test/Preprocessor/constants.c (+40)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f8f4dfbafb4f8..6c86406ef36db 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -351,6 +351,14 @@ Bug Fixes in This Version
 - Defining an integer literal suffix (e.g., ``LL``) before including
   ``<stdint.h>`` in a freestanding build no longer causes invalid token pasting
   when using the ``INTn_C`` macros. (#GH85995)
+- Clang no longer accepts invalid integer constants which are too large to fit
+  into any (standard or extended) integer type when the constant is unevaluated.
+  Merely forming the token is sufficient to render the program invalid. Code
+  like this was previously accepted and is now rejected (#GH134658):
+  .. code-block:: c
+
+    #if 1 ? 1 : 999999999999999999999
+    #endif
 
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Lex/PPExpressions.cpp b/clang/lib/Lex/PPExpressions.cpp
index b031571907441..6a6762828a20e 100644
--- a/clang/lib/Lex/PPExpressions.cpp
+++ b/clang/lib/Lex/PPExpressions.cpp
@@ -345,9 +345,8 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
     // Parse the integer literal into Result.
     if (Literal.GetIntegerValue(Result.Val)) {
       // Overflow parsing integer literal.
-      if (ValueLive)
-        PP.Diag(PeekTok, diag::err_integer_literal_too_large)
-            << /* Unsigned */ 1;
+      PP.Diag(PeekTok, diag::err_integer_literal_too_large)
+          << /* Unsigned */ 1;
       Result.Val.setIsUnsigned(true);
     } else {
       // Set the signedness of the result to match whether there was a U suffix
diff --git a/clang/test/Preprocessor/constants.c b/clang/test/Preprocessor/constants.c
new file mode 100644
index 0000000000000..d6241a4f1ceee
--- /dev/null
+++ b/clang/test/Preprocessor/constants.c
@@ -0,0 +1,40 @@
+// RUN: %clang_cc1 -E -verify %s
+
+// C++ [lex.icon]p4 and C 6.4.4.1p2 + 6.4.4.2p7 both require C and C++ to
+// validate the integer constant value when converting a preprocessing token
+// into a token for semantic analysis, even within the preprocessor itself.
+
+// Plain integer constant.
+#if 999999999999999999999 // expected-error {{integer literal is too large to be represented in any integer type}}
+#endif
+
+// These cases were previously incorrectly accepted. See GH134658.
+
+// Integer constant in an unevaluated branch of a conditional.
+#if 1 ? 1 : 999999999999999999999 // expected-error {{integer literal is too large to be represented in any integer type}}
+#endif
+
+// Integer constant in an unevaluated operand of a logical operator.
+#if 0 && 999999999999999999999 // expected-error {{integer literal is too large to be represented in any integer type}}
+#endif
+
+#if 1 || 999999999999999999999 // expected-error {{integer literal is too large to be represented in any integer type}}
+#endif
+
+// Make sure we also catch it in an elif condition.
+#if 0
+#elif 1 || 999999999999999999999 // expected-error {{integer literal is too large to be represented in any integer type}}
+#endif
+
+// However, if the block is skipped entirely, then it doesn't matter how
+// invalid the constant value is.
+#if 0
+int x = 999999999999999999999;
+
+#if 999999999999999999999
+#endif
+
+#if 0 && 999999999999999999999
+#endif
+
+#endif

Copy link

github-actions bot commented Apr 8, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

Copy link
Collaborator

@zygoloid zygoloid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

I suppose if people complain, we can make the non-live value case a warning rather than an error, but given no other implementation does, I think it makes sense not to do that speculatively.

@AaronBallman AaronBallman merged commit 9ba1a3f into llvm:main Apr 8, 2025
9 of 11 checks passed
@AaronBallman AaronBallman deleted the aballman-gh134658 branch April 8, 2025 18:26
@llvm-ci
Copy link
Collaborator

llvm-ci commented Apr 8, 2025

LLVM Buildbot has detected a new failure on builder llvm-clang-aarch64-darwin running on doug-worker-4 while building clang at step 6 "test-build-unified-tree-check-all".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/190/builds/17916

Here is the relevant piece of the build log for the reference
Step 6 (test-build-unified-tree-check-all) failure: test (failure)
******************** TEST 'LLVM :: ExecutionEngine/OrcLazy/multiple-compile-threads-basic.ll' FAILED ********************
Exit Code: 2

Command Output (stderr):
--
/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/lli -jit-kind=orc-lazy -compile-threads=2 -thread-entry hello /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/llvm/test/ExecutionEngine/OrcLazy/multiple-compile-threads-basic.ll | /Users/buildbot/buildbot-root/aarch64-darwin/build/bin/FileCheck /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/llvm/test/ExecutionEngine/OrcLazy/multiple-compile-threads-basic.ll # RUN: at line 1
+ /Users/buildbot/buildbot-root/aarch64-darwin/build/bin/lli -jit-kind=orc-lazy -compile-threads=2 -thread-entry hello /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/llvm/test/ExecutionEngine/OrcLazy/multiple-compile-threads-basic.ll
+ /Users/buildbot/buildbot-root/aarch64-darwin/build/bin/FileCheck /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/llvm/test/ExecutionEngine/OrcLazy/multiple-compile-threads-basic.ll
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
 #0 0x00000001015af9bc llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/lli+0x100ed39bc)
 #1 0x00000001015ada40 llvm::sys::RunSignalHandlers() (/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/lli+0x100ed1a40)
 #2 0x00000001015b0078 SignalHandler(int, __siginfo*, void*) (/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/lli+0x100ed4078)
 #3 0x000000018db57584 (/usr/lib/system/libsystem_platform.dylib+0x18047b584)
 #4 0x000000018db2621c (/usr/lib/system/libsystem_pthread.dylib+0x18044a21c)
 #5 0x000000018da4cad0 (/usr/lib/libc++.1.dylib+0x180370ad0)
 #6 0x0000000101151960 void llvm::detail::UniqueFunctionBase<void, llvm::Expected<llvm::DenseMap<llvm::orc::SymbolStringPtr, llvm::orc::ExecutorSymbolDef, llvm::DenseMapInfo<llvm::orc::SymbolStringPtr, void>, llvm::detail::DenseMapPair<llvm::orc::SymbolStringPtr, llvm::orc::ExecutorSymbolDef>>>>::CallImpl<llvm::orc::Platform::lookupInitSymbols(llvm::orc::ExecutionSession&, llvm::DenseMap<llvm::orc::JITDylib*, llvm::orc::SymbolLookupSet, llvm::DenseMapInfo<llvm::orc::JITDylib*, void>, llvm::detail::DenseMapPair<llvm::orc::JITDylib*, llvm::orc::SymbolLookupSet>> const&)::$_45>(void*, llvm::Expected<llvm::DenseMap<llvm::orc::SymbolStringPtr, llvm::orc::ExecutorSymbolDef, llvm::DenseMapInfo<llvm::orc::SymbolStringPtr, void>, llvm::detail::DenseMapPair<llvm::orc::SymbolStringPtr, llvm::orc::ExecutorSymbolDef>>>&) (/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/lli+0x100a75960)
 #7 0x000000010114d594 llvm::orc::AsynchronousSymbolQuery::handleComplete(llvm::orc::ExecutionSession&)::RunQueryCompleteTask::run() (/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/lli+0x100a71594)
 #8 0x000000010120980c void* std::__1::__thread_proxy[abi:un170006]<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, llvm::orc::DynamicThreadPoolTaskDispatcher::dispatch(std::__1::unique_ptr<llvm::orc::Task, std::__1::default_delete<llvm::orc::Task>>)::$_0>>(void*) (/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/lli+0x100b2d80c)
 #9 0x000000018db26f94 (/usr/lib/system/libsystem_pthread.dylib+0x18044af94)
#10 0x000000018db21d34 (/usr/lib/system/libsystem_pthread.dylib+0x180445d34)
FileCheck error: '<stdin>' is empty.
FileCheck command line:  /Users/buildbot/buildbot-root/aarch64-darwin/build/bin/FileCheck /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/llvm/test/ExecutionEngine/OrcLazy/multiple-compile-threads-basic.ll

--

********************


var-const pushed a commit to ldionne/llvm-project that referenced this pull request Apr 17, 2025
…llvm#134884)

Clang was previously accepting invalid code like:
```
  #if 1 ? 1 : 999999999999999999999
  #endif
```
because the integer constant (which is too large to fit into any
standard or extended integer type) was in an unevaluated branch of the
conditional operator. Similar invalid code involving || or && was also
accepted and is now rejected.

Fixes llvm#134658
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
accepts-invalid c c++ clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Clang not diagnosing invalid literals in subexpressions within a preprocessor conditional
5 participants