projectM-visualizer / projectM-visualizer/projectm

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

Open
#993 3 comments 0 reactions 1 assignee View on GitHub

@kblaschke is already working on this.

Since Apr 24, 2026.

bug
Dominant language
C++
Stars
4.5k
Forks
485
Avg merge
3d 7h
Merged PRs (30d)
5

Description

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.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.