Skip to content

Commit 01c2d77

Browse files
akoclaude
andcommitted
fix(#429): prevent SIGSEGV in buildPublishedRestResourceDef on malformed REST syntax
ANTLR error-recovery leaves STRING_LITERAL() nil when the publishedRestResource rule cannot match (e.g. `end resource` keyword-style or missing opening brace). The bare GetText() call on the nil token caused a SIGSEGV. Add a nil guard at the top of buildPublishedRestResourceDef so it returns nil instead of crashing. Guard both call sites (CREATE path and ALTER ADD RESOURCE path) to skip nil results rather than appending them. Regression test added: Build() on the exact crash input must not panic. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent b3b41c5 commit 01c2d77

2 files changed

Lines changed: 22 additions & 3 deletions

File tree

mdl/visitor/visitor_rest.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -373,15 +373,21 @@ func (b *Builder) ExitCreatePublishedRestServiceStatement(ctx *parser.CreatePubl
373373
// Parse resources
374374
for _, resCtx := range ctx.AllPublishedRestResource() {
375375
rc := resCtx.(*parser.PublishedRestResourceContext)
376-
stmt.Resources = append(stmt.Resources, buildPublishedRestResourceDef(rc))
376+
if res := buildPublishedRestResourceDef(rc); res != nil {
377+
stmt.Resources = append(stmt.Resources, res)
378+
}
377379
}
378380

379381
b.statements = append(b.statements, stmt)
380382
}
381383

382384
// buildPublishedRestResourceDef converts a PublishedRestResourceContext to a
383385
// PublishedRestResourceDef AST node. Shared by CREATE and ALTER.
386+
// Returns nil when the resource name token is absent (ANTLR error-recovery path).
384387
func buildPublishedRestResourceDef(rc *parser.PublishedRestResourceContext) *ast.PublishedRestResourceDef {
388+
if rc.STRING_LITERAL() == nil {
389+
return nil
390+
}
385391
resDef := &ast.PublishedRestResourceDef{
386392
Name: unquoteString(rc.STRING_LITERAL().GetText()),
387393
}
@@ -472,8 +478,9 @@ func (b *Builder) exitAlterPublishedRestServiceStatement(ctx *parser.AlterStatem
472478
// ADD RESOURCE 'name' { ... }
473479
if ac.ADD() != nil {
474480
if rc := ac.PublishedRestResource(); rc != nil {
475-
resDef := buildPublishedRestResourceDef(rc.(*parser.PublishedRestResourceContext))
476-
stmt.Actions = append(stmt.Actions, &ast.PublishedRestAddResourceAction{Resource: resDef})
481+
if resDef := buildPublishedRestResourceDef(rc.(*parser.PublishedRestResourceContext)); resDef != nil {
482+
stmt.Actions = append(stmt.Actions, &ast.PublishedRestAddResourceAction{Resource: resDef})
483+
}
477484
}
478485
continue
479486
}

mdl/visitor/visitor_rest_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,3 +88,15 @@ func TestCreatePublishedRestService(t *testing.T) {
8888
t.Errorf("Expected 2 operations, got %d", len(stmt.Resources[0].Operations))
8989
}
9090
}
91+
92+
// TestCreatePublishedRestService_EndResourceSyntax_NoPanic verifies that the
93+
// unsupported `end resource` keyword syntax does not cause a SIGSEGV (issue #429).
94+
// ANTLR error recovery produces a PublishedRestResourceContext with a nil
95+
// STRING_LITERAL token; the nil guard in buildPublishedRestResourceDef must
96+
// prevent the panic and let Build return without crashing.
97+
func TestCreatePublishedRestService_EndResourceSyntax_NoPanic(t *testing.T) {
98+
input := "create published rest service MyModule.TestREST (Version: '1.0', Path: '/api') resource 'items' get '/all' microflow MyModule.GetItems; end resource;"
99+
// Must not panic — parse errors are acceptable, a crash is not.
100+
prog, _ := Build(input)
101+
_ = prog
102+
}

0 commit comments

Comments
 (0)