Skip to content

[DEV BUG] Crash in presets that cause hlslparser's preprocessor to underflow #993

@jecassis

Description

@jecassis

Please confirm the following points:

  • This report is NOT about the Android apps in the Play Store
  • I have searched the project page to check if the issue was already reported

Affected Project

libprojectM (including the playlist library)

Affected Version

4.1.6

Operating Systems and Architectures

Windows (x64)

Build Tools

Compiler: Microsoft Windows SDK

Additional Project, OS and Toolset Details

Using Visual Studio 2026 with MSVC Build Tools 195035729.
Project files were generated using the standard CMake flow, using the default arguments.

Type of Defect

Crash (unhandled exceptions, segmentation faults)

Log Output

No log output was provided. With the debugger crash is an assertion in <stack>.

Describe the Issue

When parsing certain presets, the preprocessor can corrupt directive text. It causes the library/application to crash.

I created a foobar2000 component that uses the libprojectM to do comparisons with MilkDrop 2. The crash brings down player with no message or usable stack trace.

To trace the crashes, built 1.4.6 projectM-4.dll and projectM-4d.dll; eval is at 1.0.6 and GLEW at 2.3.1.
Crash can be reproduced using "BigWings + IkeC + MilkDrop2077 + Se7enSlasher - Heartless3 (Invertless Edit).milk".

A minimal reproduction is the following in the shader code:

#define HAS_HEART
#define USE_POST_PROCESSING 1
#ifdef HAS_HEART
float T = 1;
#endif
float x = 0;

At crash time, sourcePreprocessed contains malformed directive text, e.g. #ifdef(#defineUSE_POST_PROCESSING). A latter #endif causes stack pop that empties isCodeActive. The next identifier-processing path calls top() on an empty stack and asserts.

There are a variety of issues that require attention:

  • Empty define handling in "HLSLParser.cpp"'s ParsePreprocessorDefine() can consume the next line because token advancement after macro name skips EOL.
  • "HLSLTokenizer.cpp"'s reserved preprocessor keywords include only #define/#if/#else/#endif. #ifdef/#ifndef/#elif are not tokenized/handled as control directives, so stack transitions can become unbalanced.
  • Stack operations in ApplyPreprocessor() assume non-empty state and assert instead of reporting syntax errors.

It should go without saying that unmatched preprocessor directives should produce parser errors, not container assertions.

Metadata

Metadata

Assignees

Labels

bugThe issue is (potentially) a bug.

Type

Projects

Status

In Progress

Status

In Progress

Relationships

None yet

Development

No branches or pull requests

Issue actions