-
Notifications
You must be signed in to change notification settings - Fork 0
NSC preprocess #4
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
Conversation
refs compiler-explorer#7948 Signed-off-by: Marc Poulhiès <dkm@kataplop.net>
refs compiler-explorer#7948 Signed-off-by: Marc Poulhiès <dkm@kataplop.net>
…xplorer#8017) - Made parsers stateful instances instead of shared static state (for mllvm options). Fixes compiler-explorer#8011 as this is caused by multiple clang-based compilers being run concurrently and stomping over each others' state. - passes `Compiler` to the constructor, which removes some param passing - Added some missing awaits - Tried to get things less dependent on `examples`, only `go` needs it - Spotted that `zig` c++ might have issues in discovery - Fly-by fixed a broken go path in ppc64le_gl122 - removed a redundant override in coccinelle - made the mojo parser actually use the parser it defined - canonified tablegen's special method - I changed the zig parser too but as best I can tell it was broken before (the `1` return value from the command it runs:) ``` ubuntu@ip-172-30-0-164:/infra/.deploy$ /opt/compiler-explorer/zig-0.14.1/zig c++ -mllvm --help-list-hidden /infra/.deploy/examples/c++/default.cpp -S -o /tmp/output.s ... --x86-use-vzeroupper - Minimize AVX to SSE transition penalty --xcore-max-threads=<number> - Maximum number of threads (for emulation thread-local storage) /infra/.deploy/examples/c++/default.cpp:1:1: error: FileNotFound ``` return code 1 (means it's not cached) --------- Co-authored-by: Partouf <partouf@gmail.com>
…er#8003) Bump Binutils version into 2.45 when using GCC 15.1. The change form 2.44 into 2.45 includes some new assembler features, the details please check https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=gas/NEWS;h=2e9538bd2736b4108cc5a383802c75f5feacfbc4;hb=2bc7af1ff7732451b6a7b09462a815c3284f9613 Signed-off-by: Jiawei <jiawei@iscas.ac.cn>
…orer#8018) Some compilers emit symbol names with multiple dots, e. g. Clang for static data (like string literals) or GCC for function clones (e. g. due to interprocedural constant propagation). Test cases: https://godbolt.org/z/dGbGncnh8, https://godbolt.org/z/dhrGGqrjo
`AsmParser.labelFindFor` was only called in tests.
…xplorer#8028) For example Rust on AArch64: https://godbolt.org/z/e3q9Wv7zj
This PR adds the C++ library **fusedkernellibrary** version Beta-0.1.9 to Compiler Explorer. - GitHub URL: https://github.com/Libraries-Openly-Fused/FusedKernelLibrary Related PR: compiler-explorer/infra#1755 --- _PR created with [ce-lib-wizard](https://github.com/compiler-explorer/ce-library-wizard)_ --------- Co-authored-by: Albert Andaluz <albertandaluz@hotmail.com> Co-authored-by: Patrick Quist <partouf@gmail.com>
This _maybe_ shows an issue - users could find _anything_ in cefs so we need to make sure we don't ever put privileged stuff in cefs.
makes the root bindmount a "slave" which means it gets all host mount point change notifications, needed for cefs automounting. Security tradeoffs mentioned in compiler-explorer/nsjail#2
ISPC v1.28.0 has been released. Related infra change: compiler-explorer/infra#1762
…rrower layout (compiler-explorer#7853) Stacked on compiler-explorer#7850 This PR implements this aspect of the cutter layout algorithm, using exact subtree shapes instead of the full bounding box  Example 1:   Example 2:  
…explorer#8038) Trying to solve the root cause: `Editor.maybeEmitChange` calls `this.eventHub.emit('editorChange')`, and then `Compiler.onEditorChange` calls `this.compile()` . So the idiom ```ts this.maybeEmitChange(); this.requestCompilation(); ``` repeated a few times in editor.ts, causes two rapid (and redundant) invocations of `compile`, which in turn cause the race. This PR removes all calls to `Editor.requestCompilation` and in fact removes the function entirely. I'm guessing `maybeEmitChange` is a late addition to solve some other problems, and this race was an unintended side effect, but please correct me if you have better understanding of the code and its history.
<!-- THIS COMMENT IS INVISIBLE IN THE FINAL PR, BUT FEEL FREE TO REMOVE IT Thanks for taking the time to improve CE. We really appreciate it. Before opening the PR, please make sure that the tests & linter pass their checks, by running `make check`. In the best case scenario, you are also adding tests to back up your changes, but don't sweat it if you don't. We can discuss them at a later date. Feel free to append your name to the CONTRIBUTORS.md file Thanks again, we really appreciate this! --> --------- Co-authored-by: Patrick Quist <partouf@gmail.com>
There are two clang reflection implementations: * The one from Matúš that implements the Reflection TS * The one from Dan that implements p2996 The latter is what will be in C++26, but that's hard to tell from the labels since the former is labeled "reflection" while the latter is labeled "experimental p2996". This changes the labels to "reflection - TS" and "relfection - C++26", respectively, to make it clearer as to which is which.
* support c++20, c++2b, c++23, c++2c * set the default standard to cpp17 as it is currently the default for both compiler-explorer and cppinsights
| const clojureOptions = _.compact([ | ||
| '-Sdeps', | ||
| this.defaultDeps, | ||
| ...classpathArgument, | ||
| ...wrapperInvokeArgument, | ||
| ...userOptions, | ||
| inputFilename, | ||
| ]); |
Check failure
Code scanning / CodeQL
Loop bound injection High
user-provided value
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 7 days ago
General approach: ensure that anything we spread or iterate over is a genuine, bounded array. For user-controlled data that may be passed as an array-like object, first validate/normalize it to a real array and, optionally, cap its length to a reasonable maximum. This prevents an attacker from supplying an object with a malicious .length value.
Concrete fix here: immediately before constructing clojureOptions in ClojureCompiler.runCompiler, normalize userOptions into a safe array and bound its length. We can do this by:
- Coercing
optionsto an array of strings, and - Deriving
userOptionsfrom that safe array instead of the possibly tainted original.
We do not need new imports; we can implement the normalization inline. A reasonable defensive limit can be chosen (e.g., 1000 options) to avoid absurdly large inputs without affecting legitimate usage.
Specific changes in lib/compilers/clojure.ts:
- After the code that determines
sourceFileOptionIndex, compute asafeOptionsarray that:- Treats non-arrays as empty.
- Converts all entries to strings.
- Truncates the number of elements to a defined maximum (e.g., 1000).
- Use
safeOptions.slice(0, sourceFileOptionIndex)(or the wholesafeOptionsif the index is-1) to deriveuserOptions. - Leave all other logic intact.
No changes are required in lib/handlers/compile.ts, lib/base-compiler.ts, or lib/compilers/win32.ts to resolve this particular loop-bound/spread issue; the mitigation at the use site in ClojureCompiler is sufficient to break the tainted flow into an unsafe spread.
-
Copy modified lines R129-R139
| @@ -126,7 +126,17 @@ | ||
| const sourceFileOptionIndex = options.findIndex(option => { | ||
| return option.endsWith('.clj'); | ||
| }); | ||
| const userOptions = options.slice(0, sourceFileOptionIndex); | ||
|
|
||
| // Normalize and bound user-controlled options to avoid untrusted length issues. | ||
| const MAX_USER_OPTIONS = 1000; | ||
| const safeOptions = Array.isArray(options) | ||
| ? options.slice(0, MAX_USER_OPTIONS).map(option => String(option)) | ||
| : []; | ||
| const userOptions = | ||
| sourceFileOptionIndex === -1 | ||
| ? safeOptions | ||
| : safeOptions.slice(0, Math.min(sourceFileOptionIndex, safeOptions.length)); | ||
|
|
||
| const classpathArgument = await this.getClojureClasspathArgument(execOptions.customCwd, compiler, execOptions); | ||
| const wrapperInvokeArgument = ['-M', this.compilerWrapperPath]; | ||
| const clojureOptions = _.compact([ |
| return option.endsWith('.clj'); | ||
| }); | ||
| const userOptions = options.slice(0, sourceFileOptionIndex); | ||
| const clojureOptions = _.compact([...userOptions, '--macro-expand', inputFilename]); |
Check failure
Code scanning / CodeQL
Loop bound injection High
user-provided value
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 7 days ago
In general, to fix loop bound injection problems on arrays coming from untrusted input, you either (a) ensure the value is a genuine array with a reasonable maximum length, or (b) avoid directly iterating/spreading over something that may not be an array (e.g., coerce it into a safe representation first).
For this specific case, the minimal, behavior-preserving fix is to normalize userOptions in generateClojureMacroExpansion to a safe array before the spread, and to ensure its length is bounded. We can do this by:
- Ensuring
userOptionsis an actual array: ifsourceFileOptionIndexis-1(source file not found), we fall back to an empty array rather thanoptions.slice(0, -1)and we explicitly cast/normalize slices to arrays. - Clamping the maximum number of options we will process (e.g., 1,000 elements), so that an attacker cannot force our code to iterate or spread across an array with an enormous
.length. - This can be implemented entirely within
lib/compilers/clojure.ts, near the existing code, without changing external behavior for normal, small inputs.
Concretely:
- In
generateClojureMacroExpansion, after computingsourceFileOptionIndex, replace the directoptions.slice(0, sourceFileOptionIndex)with logic that:- Treats
sourceFileOptionIndex < 0or!Array.isArray(options)as “no user options”. - Limits the slice to a maximum length (e.g.,
MAX_USER_OPTIONS = 1000).
- Treats
- Use this sanitized
userOptionswhen buildingclojureOptions.
No other files (compile.ts, base-compiler.ts, win32.ts) need changes for this particular alert; the taint chain there is already constrained by other internal processing, and the direct unbounded spread is only in ClojureCompiler.generateClojureMacroExpansion.
-
Copy modified lines R153-R160
| @@ -150,7 +150,14 @@ | ||
| const sourceFileOptionIndex = options.findIndex(option => { | ||
| return option.endsWith('.clj'); | ||
| }); | ||
| const userOptions = options.slice(0, sourceFileOptionIndex); | ||
| // Ensure we only work with a real array of reasonable size to avoid | ||
| // potential DoS from a maliciously large or spoofed "options" value. | ||
| const MAX_USER_OPTIONS = 1000; | ||
| let userOptions: string[] = []; | ||
| if (Array.isArray(options) && sourceFileOptionIndex > 0) { | ||
| const safeEnd = Math.min(sourceFileOptionIndex, MAX_USER_OPTIONS); | ||
| userOptions = options.slice(0, safeEnd); | ||
| } | ||
| const clojureOptions = _.compact([...userOptions, '--macro-expand', inputFilename]); | ||
| const output = await this.runCompiler( | ||
| this.compiler.exe, |
lib/compilers/nim.ts
Outdated
Check failure
Code scanning / CodeQL
Loop bound injection High
user-provided value
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 7 days ago
In general, to fix this class of issue you must ensure that any value whose .length ends up driving iteration is either: (a) guaranteed by type and construction to be a safe array, or (b) validated and normalized before use. Here, result.compilationOptions comes from tainted input and is later used with _.intersection, which treats it as array‑like. The safest fix is to defensively normalize options inside NimCompiler.postProcess so that it is always a bounded string[] regardless of what upstream provided.
Concretely, in lib/compilers/nim.ts within postProcess, we will:
- Replace the direct assignment
const options = result.compilationOptions;with a small normalization step:- If
result.compilationOptionsis already an array, use it. - If it is a string, wrap it as a single‑element array.
- Otherwise, fall back to an empty array.
- If
- Optionally, enforce a reasonable maximum length for safety (e.g., clamp to some high upper bound), but to avoid altering expected behavior we will only normalize type, not truncate.
- Use this normalized local
optionsin the calls to_.intersectionandgetCacheFile, eliminating the use of the non‑null assertionoptions!.
This keeps existing functionality intact for valid inputs (arrays of options) while preventing a malicious request from supplying a non‑array with a malicious .length value.
Only lib/compilers/nim.ts needs changes.
-
Copy modified lines R100-R105 -
Copy modified line R108 -
Copy modified line R111
| @@ -97,13 +97,18 @@ | ||
| outputFilename: string, | ||
| filters: ParseFiltersAndOutputOptions, | ||
| ) { | ||
| const options = result.compilationOptions; | ||
| const rawOptions = result.compilationOptions; | ||
| const options: string[] = Array.isArray(rawOptions) | ||
| ? rawOptions | ||
| : typeof rawOptions === 'string' | ||
| ? [rawOptions] | ||
| : []; | ||
| const cacheDir = this.cacheDir(outputFilename); | ||
| try { | ||
| if (_.intersection(options!, ['js', 'check', '-c']).length > 0) filters.binary = false; | ||
| if (_.intersection(options, ['js', 'check', '-c']).length > 0) filters.binary = false; | ||
| else { | ||
| filters.binary = true; | ||
| const objFile = unwrap(this.getCacheFile(options!, result.inputFilename!, cacheDir)); | ||
| const objFile = unwrap(this.getCacheFile(options, result.inputFilename!, cacheDir)); | ||
| if (await utils.fileExists(objFile)) { | ||
| await fs.rename(objFile, outputFilename); | ||
| } else { |
|
wtf copilot why you review my pr |
No description provided.