Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions src/core/preprocessor.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ const LOOP_INDEX = /\{i\}/g;
// matches color attachments, for example: pcFragColor1
const FRAGCOLOR = /(pcFragColor[1-8])\b/g;

// matches a pure numeric literal (integer or decimal, no sign since - is blocked by INVALID)
const NUMERIC_LITERAL = /^\d+(?:\.\d+)?$/;

/**
* Pure static class implementing subset of C-style preprocessor.
* inspired by: https://github.com/dcodeIO/Preprocessor.js
Expand Down Expand Up @@ -539,9 +542,9 @@ class Preprocessor {
}

// Handle numeric literals (0 is false, non-zero is true) - standard C preprocessor behavior
const num = parseFloat(expr);
if (!isNaN(num)) {
return { result: num !== 0, error };
// Only match pure numeric literals to avoid incorrectly parsing expressions like "3 == 3"
if (NUMERIC_LITERAL.test(expr)) {
return { result: parseFloat(expr) !== 0, error };
}

// Handle defined(expr) and !defined(expr)
Expand Down
30 changes: 30 additions & 0 deletions test/core/preprocessor.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,22 @@ describe('Preprocessor', function () {
#if 0 || defined(A)
NUM6
#endif

// Edge cases: expressions starting with numbers should not be parsed as numeric literals
// Note: numeric comparisons like "3 == 3" are not supported (COMPARISON regex requires
// left operand to start with a letter), but we must ensure they don't incorrectly
// evaluate to true due to parseFloat("3 == 3") returning 3
#if 3 == 3
EDGE1
#endif

#if 0 != 1
EDGE2
#endif

#if 5 > 3
EDGE3
#endif
`;

it('returns false for MORPH_A', function () {
Expand Down Expand Up @@ -405,4 +421,18 @@ describe('Preprocessor', function () {
it('returns true for NUM6 (#if 0 || defined(A))', function () {
expect(Preprocessor.run(srcData, includes).includes('NUM6')).to.equal(true);
});

// Edge case tests: expressions starting with numbers must not be parsed as numeric literals
// These are unsupported expressions, but should evaluate to false rather than incorrectly true
it('returns false for EDGE1 (#if 3 == 3 is unsupported, must not parse "3" as truthy)', function () {
expect(Preprocessor.run(srcData, includes).includes('EDGE1')).to.equal(false);
});

it('returns false for EDGE2 (#if 0 != 1 is unsupported, must not parse "0" as falsy for wrong reason)', function () {
expect(Preprocessor.run(srcData, includes).includes('EDGE2')).to.equal(false);
});

it('returns false for EDGE3 (#if 5 > 3 is unsupported, must not parse "5" as truthy)', function () {
expect(Preprocessor.run(srcData, includes).includes('EDGE3')).to.equal(false);
});
});
Loading