fix attempted OOB access with broken swtich/case syntax

This commit is contained in:
WebFreak001 2025-12-27 18:17:28 +01:00 committed by Jan Jurzitza
parent 4d7e4f5f81
commit 9dc3d0d1d1
1 changed files with 56 additions and 6 deletions

View File

@ -1,7 +1,7 @@
module dscanner.analysis.base; module dscanner.analysis.base;
import dparse.ast; import dparse.ast;
import dparse.lexer : IdType, str, Token, tok; import dparse.lexer : IdType, str, tok, Token;
import dscanner.analysis.nolint; import dscanner.analysis.nolint;
import dsymbol.scope_ : Scope; import dsymbol.scope_ : Scope;
import std.array; import std.array;
@ -639,12 +639,13 @@ public:
{ {
// case and default statements always open new scopes and close // case and default statements always open new scopes and close
// previous case scopes // previous case scopes
bool close = switchStack.length && switchStack[$ - 1].inCase; bool wasInCase = switchStack.length && switchStack[$ - 1].inCase;
bool b = switchStack[$ - 1].inCase; if (switchStack.length)
switchStack[$ - 1].inCase = true; switchStack[$ - 1].inCase = true;
scope (exit) scope (exit)
switchStack[$ - 1].inCase = b; if (switchStack.length)
if (close) switchStack[$ - 1].inCase = wasInCase;
if (wasInCase)
{ {
popScope(); popScope();
pushScope(); pushScope();
@ -897,3 +898,52 @@ unittest
auto isOldScope = void; auto isOldScope = void;
}); });
} }
// test previous segfault
unittest
{
import dparse.lexer : getTokensForParser, LexerConfig, StringCache;
import dparse.parser : parseModule;
import dparse.rollback_allocator : RollbackAllocator;
StringCache cache = StringCache(4096);
LexerConfig config;
RollbackAllocator rba;
auto tokens = getTokensForParser(q{
module derp;
void main(string[] args)
{
foreach
switch (x)
{
case 1:
if (y) {
continue;
}
break;
default:
break;
}
}
}, config, &cache);
auto m = parseModule(tokens, "stdin", &rba);
class TestScopedAnalyzer : ScopedBaseAnalyzer
{
this()
{
super(BaseAnalyzerArguments("stdin"));
}
override protected void pushScope()
{
}
override protected void popScope()
{
}
}
new TestScopedAnalyzer().visit(m);
}