parser: validate scoped external names
PATCH 1/1 parser: validate scoped external names
Centralize parsing of D scoping markers used by external type and symbol references. The helper now returns the resolved scope and identifier pieces, supports kernel and userspace markers for both type and symbol lookup, and rejects empty operands, runs longer than two backticks, and repeated scoping markers as D_SYNTAX instead of falling through to lookup failures.
Recognize dotted scoped identifiers as a single lexer token so module names like foo.bar resolve as one external symbol reference.
Add lexer and type regression tests for malformed scoped identifiers, dotted scopes, empty scope operands, scope-kind mismatches, and scoping operators in declarations. Update the sizeof unknown-symbol test to use a non-empty symbol name.
--- libdtrace/dt_decl.c | 6 +- libdtrace/dt_lex.l | 5 + libdtrace/dt_parser.c | 140 ++++++++++++------ libdtrace/dt_parser.h | 1 + .../err.D_IDENT_UNDEF.scope-dot-kernel.d | 19 +++ .../err.D_IDENT_UNDEF.scope-dot-kernel.r | 2 + .../lexer/err.D_IDENT_UNDEF.scope-dot.d | 19 +++ .../lexer/err.D_IDENT_UNDEF.scope-dot.r | 2 + .../err.D_SYM_BADREF.scope-kernel-as-user.d | 18 +++ .../err.D_SYM_BADREF.scope-kernel-as-user.r | 2 + .../err.D_SYM_BADREF.scope-user-as-kernel.d | 20 +++ .../err.D_SYM_BADREF.scope-user-as-kernel.r | 2 + .../err.D_SYNTAX.scope-empty-bare-user.d | 19 +++ .../err.D_SYNTAX.scope-empty-bare-user.r | 2 + .../lexer/err.D_SYNTAX.scope-empty-bare.d | 19 +++ .../lexer/err.D_SYNTAX.scope-empty-bare.r | 2 + .../lexer/err.D_SYNTAX.scope-empty-dot-user.d | 19 +++ .../lexer/err.D_SYNTAX.scope-empty-dot-user.r | 2 + .../lexer/err.D_SYNTAX.scope-empty-user.d | 19 +++ .../lexer/err.D_SYNTAX.scope-empty-user.r | 2 + .../unittest/lexer/err.D_SYNTAX.scope-empty.d | 18 +++ .../unittest/lexer/err.D_SYNTAX.scope-empty.r | 2 + .../lexer/err.D_SYNTAX.scope-multiple.d | 19 +++ .../lexer/err.D_SYNTAX.scope-multiple.r | 2 + .../lexer/err.D_SYNTAX.scope-triple.d | 19 +++ .../lexer/err.D_SYNTAX.scope-triple.r | 2 + test/unittest/lexer/tst.scope-user-explicit.d | 22 +++ .../sizeof/err.D_IDENT_UNDEF.UnknownSymbol.d | 2 +- .../sizeof/err.D_IDENT_UNDEF.UnknownSymbol.r | 2 +- .../err.D_DECL_SCOPE.scopeop-enumerator.d | 16 ++ .../err.D_DECL_SCOPE.scopeop-enumerator.r | 2 + .../types/err.D_DECL_SCOPE.scopeop-ident.d | 19 +++ .../types/err.D_DECL_SCOPE.scopeop-ident.r | 2 + .../types/err.D_DECL_SCOPE.scopeop-member.d | 16 ++ .../types/err.D_DECL_SCOPE.scopeop-member.r | 2 + 35 files changed, 414 insertions(+), 51 deletions(-) create mode 100644 test/unittest/lexer/err.D_IDENT_UNDEF.scope-dot-kernel.d create mode 100644 test/unittest/lexer/err.D_IDENT_UNDEF.scope-dot-kernel.r create mode 100644 test/unittest/lexer/err.D_IDENT_UNDEF.scope-dot.d create mode 100644 test/unittest/lexer/err.D_IDENT_UNDEF.scope-dot.r create mode 100644 test/unittest/lexer/err.D_SYM_BADREF.scope-kernel-as-user.d create mode 100644 test/unittest/lexer/err.D_SYM_BADREF.scope-kernel-as-user.r create mode 100644 test/unittest/lexer/err.D_SYM_BADREF.scope-user-as-kernel.d create mode 100644 test/unittest/lexer/err.D_SYM_BADREF.scope-user-as-kernel.r create mode 100644 test/unittest/lexer/err.D_SYNTAX.scope-empty-bare-user.d create mode 100644 test/unittest/lexer/err.D_SYNTAX.scope-empty-bare-user.r create mode 100644 test/unittest/lexer/err.D_SYNTAX.scope-empty-bare.d create mode 100644 test/unittest/lexer/err.D_SYNTAX.scope-empty-bare.r create mode 100644 test/unittest/lexer/err.D_SYNTAX.scope-empty-dot-user.d create mode 100644 test/unittest/lexer/err.D_SYNTAX.scope-empty-dot-user.r create mode 100644 test/unittest/lexer/err.D_SYNTAX.scope-empty-user.d create mode 100644 test/unittest/lexer/err.D_SYNTAX.scope-empty-user.r create mode 100644 test/unittest/lexer/err.D_SYNTAX.scope-empty.d create mode 100644 test/unittest/lexer/err.D_SYNTAX.scope-empty.r create mode 100644 test/unittest/lexer/err.D_SYNTAX.scope-multiple.d create mode 100644 test/unittest/lexer/err.D_SYNTAX.scope-multiple.r create mode 100644 test/unittest/lexer/err.D_SYNTAX.scope-triple.d create mode 100644 test/unittest/lexer/err.D_SYNTAX.scope-triple.r create mode 100644 test/unittest/lexer/tst.scope-user-explicit.d create mode 100644 test/unittest/types/err.D_DECL_SCOPE.scopeop-enumerator.d create mode 100644 test/unittest/types/err.D_DECL_SCOPE.scopeop-enumerator.r create mode 100644 test/unittest/types/err.D_DECL_SCOPE.scopeop-ident.d create mode 100644 test/unittest/types/err.D_DECL_SCOPE.scopeop-ident.r create mode 100644 test/unittest/types/err.D_DECL_SCOPE.scopeop-member.d create mode 100644 test/unittest/types/err.D_DECL_SCOPE.scopeop-member.r
libdtrace/dt_decl.c +2 -4
@@ -233,10 +233,8 @@ dt_decl_spec(ushort_t kind, char *name) ddp->dd_kind = kind; ddp->dd_name = name; -if (name !=NULL &&strchr (name,'`' ) !=NULL ) { -xyerror (D_DECL_SCOPE ,"D scoping operator may not be used " -"in a type name\n" ); - } +if (name !=NULL &&dt_scope_parse (name,NULL ,NULL ) <0 ) +xyerror (D_SYNTAX ,"syntax error near \"%s\"\n" , name);return dt_decl_check (ddp); }
libdtrace/dt_lex.l +5 -0
@@ -50,6 +50,7 @@ static size_t dt_input(char *buf, size_t max_size); RGX_AGG "@"[a-zA-Z_][0-9a-zA-Z_]* RGX_PSPEC [-$:a-zA-Z_.?*\\\[\]!][-$:0-9a-zA-Z_.`?*\\\[\]!]* RGX_IDENT ([a-zA-Z_`][0-9a-zA-Z_`]*)|([0-9][0-9a-zA-Z_]*`[0-9a-zA-Z_`]*) +RGX_SCOPE_IDENT [0-9a-zA-Z_][0-9a-zA-Z_]*(\.[0-9a-zA-Z_]+)+``?[0-9a-zA-Z_]+ RGX_INT ([0-9]+|0[xX][0-9A-Fa-f]+)[uU]?[lL]?[lL]? RGX_FP ([0-9]+("."?)[0-9]*|"."[0-9]+)((e|E)("+"|-)?[0-9]+)?[fFlL]? RGX_WS [\f\n\r\t\v ]
@@ -299,6 +300,7 @@ if (yypcb->pcb_token != 0) { return DT_TOK_INT; } +<S0>{RGX_SCOPE_IDENT} | <S0,SIDENT>{RGX_IDENT} { return id_or_type(yytext); }
@@ -728,6 +730,9 @@ id_or_type(const char *s) int c0, c1; dt_ident_t *idp; + if (dt_scope_parse(s, NULL, NULL) < 0) + xyerror(D_SYNTAX, "syntax error near \"%s\"\n", s); + if ((s = yylval.l_str = strdup(s)) == NULL) longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
libdtrace/dt_parser.c +95 -45
194 lines not on this page · raw message
libdtrace/dt_parser.h +1 -0
@@ -211,6 +211,7 @@ extern dt_node_t *dt_node_tstring(dt_node_t *, uintmax_t);extern dt_node_t *dt_node_link (dt_node_t *,dt_node_t *);extern dt_node_t *dt_node_cook (dt_node_t *,uint_t );extern void dt_cook_taint_alloca (dt_node_t *,dt_ident_t *,dt_node_t *); +extern int dt_scope_parse (const char *,const char **,const char **);extern dt_node_t *dt_node_xalloc (dtrace_hdl_t *,int );extern void dt_node_free (dt_node_t *);
test/unittest/lexer/err.D_IDENT_UNDEF.scope-dot-kernel.d new file +19 -0
@@ -0,0 +1,19 @@ +/* + * Oracle Linux DTrace. + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * Licensed under the Universal Permissive License v 1.0 as shown at + * http://oss.oracle.com/licenses/upl. + */ + +/* + * ASSERTION: Dotted kernel module scopes lex as a single external symbol + * reference. + */ + +#pragma D option quiet + +BEGIN +{ + trace(foo.bar`baz); + exit(0); +}
test/unittest/lexer/err.D_IDENT_UNDEF.scope-dot-kernel.r new file +2 -0
@@ -0,0 +1,2 @@ +-- @@stderr -- +dtrace: failed to compile script test/unittest/lexer/err.D_IDENT_UNDEF.scope-dot-kernel.d: [D_IDENT_UNDEF] line 17: failed to resolve foo.bar`baz: Module is no longer loaded
test/unittest/lexer/err.D_IDENT_UNDEF.scope-dot.d new file +19 -0
@@ -0,0 +1,19 @@ +/* + * Oracle Linux DTrace. + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * Licensed under the Universal Permissive License v 1.0 as shown at + * http://oss.oracle.com/licenses/upl. + */ + +/* + * ASSERTION: Dotted userspace module scopes lex as a single external symbol + * reference. + */ + +#pragma D option quiet + +BEGIN +{ + trace(foo.bar``baz); + exit(0); +}
test/unittest/lexer/err.D_IDENT_UNDEF.scope-dot.r new file +2 -0
@@ -0,0 +1,2 @@ +-- @@stderr -- +dtrace: failed to compile script test/unittest/lexer/err.D_IDENT_UNDEF.scope-dot.d: [D_IDENT_UNDEF] line 17: failed to resolve foo.bar``baz: Module is no longer loaded
test/unittest/lexer/err.D_SYM_BADREF.scope-kernel-as-user.d new file +18 -0
@@ -0,0 +1,18 @@ +/* + * Oracle Linux DTrace. + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * Licensed under the Universal Permissive License v 1.0 as shown at + * http://oss.oracle.com/licenses/upl. + */ + +/* + * ASSERTION: Kernel symbols cannot be referenced using userspace scoping. + */ + +#pragma D option quiet + +BEGIN +{ + trace(vmlinux``major_names); + exit(0); +}
test/unittest/lexer/err.D_SYM_BADREF.scope-kernel-as-user.r new file +2 -0
@@ -0,0 +1,2 @@ +-- @@stderr -- +dtrace: failed to compile script test/unittest/lexer/err.D_SYM_BADREF.scope-kernel-as-user.d: [D_SYM_BADREF] line 16: kernel module 'vmlinux' symbol 'major_names' may not be referenced as a user symbol
test/unittest/lexer/err.D_SYM_BADREF.scope-user-as-kernel.d new file +20 -0
@@ -0,0 +1,20 @@ +/* + * Oracle Linux DTrace. + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * Licensed under the Universal Permissive License v 1.0 as shown at + * http://oss.oracle.com/licenses/upl. + */ + +/* @@trigger: testprobe */ + +/* + * ASSERTION: Userspace symbols cannot be referenced using kernel scoping. + */ + +#pragma D option quiet + +BEGIN +{ + trace(&testprobe`main); + exit(0); +}
test/unittest/lexer/err.D_SYM_BADREF.scope-user-as-kernel.r new file +2 -0
@@ -0,0 +1,2 @@ +-- @@stderr -- +dtrace: failed to compile script test/unittest/lexer/err.D_SYM_BADREF.scope-user-as-kernel.d: [D_SYM_BADREF] line 18: user module 'testprobe' symbol 'main' may not be referenced as a kernel symbol
test/unittest/lexer/err.D_SYNTAX.scope-empty-bare-user.d new file +19 -0
@@ -0,0 +1,19 @@ +/* + * Oracle Linux DTrace. + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * Licensed under the Universal Permissive License v 1.0 as shown at + * http://oss.oracle.com/licenses/upl. + */ + +/* + * ASSERTION: A bare userspace D scoping operator with an empty identifier is a + * syntax error. + */ + +#pragma D option quiet + +BEGIN +{ + trace(``); + exit(0); +}
test/unittest/lexer/err.D_SYNTAX.scope-empty-bare-user.r new file +2 -0
@@ -0,0 +1,2 @@ +-- @@stderr -- +dtrace: failed to compile script test/unittest/lexer/err.D_SYNTAX.scope-empty-bare-user.d: [D_SYNTAX] line 17: syntax error near "``"
test/unittest/lexer/err.D_SYNTAX.scope-empty-bare.d new file +19 -0
@@ -0,0 +1,19 @@ +/* + * Oracle Linux DTrace. + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * Licensed under the Universal Permissive License v 1.0 as shown at + * http://oss.oracle.com/licenses/upl. + */ + +/* + * ASSERTION: A bare D scoping operator with an empty identifier is a syntax + * error. + */ + +#pragma D option quiet + +BEGIN +{ + trace(`); + exit(0); +}
test/unittest/lexer/err.D_SYNTAX.scope-empty-bare.r new file +2 -0
@@ -0,0 +1,2 @@ +-- @@stderr -- +dtrace: failed to compile script test/unittest/lexer/err.D_SYNTAX.scope-empty-bare.d: [D_SYNTAX] line 17: syntax error near "`"
test/unittest/lexer/err.D_SYNTAX.scope-empty-dot-user.d new file +19 -0
@@ -0,0 +1,19 @@ +/* + * Oracle Linux DTrace. + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * Licensed under the Universal Permissive License v 1.0 as shown at + * http://oss.oracle.com/licenses/upl. + */ + +/* + * ASSERTION: A dotted userspace D scoping operator with an empty identifier is + * a syntax error. + */ + +#pragma D option quiet + +BEGIN +{ + trace(foo.bar``); + exit(0); +}
test/unittest/lexer/err.D_SYNTAX.scope-empty-dot-user.r new file +2 -0
@@ -0,0 +1,2 @@ +-- @@stderr -- +dtrace: failed to compile script test/unittest/lexer/err.D_SYNTAX.scope-empty-dot-user.d: [D_SYNTAX] line 17: syntax error near "bar``"
test/unittest/lexer/err.D_SYNTAX.scope-empty-user.d new file +19 -0
@@ -0,0 +1,19 @@ +/* + * Oracle Linux DTrace. + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * Licensed under the Universal Permissive License v 1.0 as shown at + * http://oss.oracle.com/licenses/upl. + */ + +/* + * ASSERTION: A userspace D scoping operator with an empty identifier is a + * syntax error. + */ + +#pragma D option quiet + +BEGIN +{ + trace(bar``); + exit(0); +}
test/unittest/lexer/err.D_SYNTAX.scope-empty-user.r new file +2 -0
@@ -0,0 +1,2 @@ +-- @@stderr -- +dtrace: failed to compile script test/unittest/lexer/err.D_SYNTAX.scope-empty-user.d: [D_SYNTAX] line 17: syntax error near "bar``"
test/unittest/lexer/err.D_SYNTAX.scope-empty.d new file +18 -0
@@ -0,0 +1,18 @@ +/* + * Oracle Linux DTrace. + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * Licensed under the Universal Permissive License v 1.0 as shown at + * http://oss.oracle.com/licenses/upl. + */ + +/* + * ASSERTION: A D scoping operator with an empty identifier is a syntax error. + */ + +#pragma D option quiet + +BEGIN +{ + trace(foo`); + exit(0); +}
test/unittest/lexer/err.D_SYNTAX.scope-empty.r new file +2 -0
@@ -0,0 +1,2 @@ +-- @@stderr -- +dtrace: failed to compile script test/unittest/lexer/err.D_SYNTAX.scope-empty.d: [D_SYNTAX] line 16: syntax error near "foo`"
test/unittest/lexer/err.D_SYNTAX.scope-multiple.d new file +19 -0
@@ -0,0 +1,19 @@ +/* + * Oracle Linux DTrace. + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * Licensed under the Universal Permissive License v 1.0 as shown at + * http://oss.oracle.com/licenses/upl. + */ + +/* + * ASSERTION: Multiple D scoping operators in one identifier are a syntax + * error. + */ + +#pragma D option quiet + +BEGIN +{ + trace(foo``bar``baz); + exit(0); +}
test/unittest/lexer/err.D_SYNTAX.scope-multiple.r new file +2 -0
@@ -0,0 +1,2 @@ +-- @@stderr -- +dtrace: failed to compile script test/unittest/lexer/err.D_SYNTAX.scope-multiple.d: [D_SYNTAX] line 17: syntax error near "foo``bar``baz"
test/unittest/lexer/err.D_SYNTAX.scope-triple.d new file +19 -0
@@ -0,0 +1,19 @@ +/* + * Oracle Linux DTrace. + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * Licensed under the Universal Permissive License v 1.0 as shown at + * http://oss.oracle.com/licenses/upl. + */ + +/* + * ASSERTION: More than two consecutive D scoping operator characters are a + * syntax error. + */ + +#pragma D option quiet + +BEGIN +{ + trace(foo```bar); + exit(0); +}
test/unittest/lexer/err.D_SYNTAX.scope-triple.r new file +2 -0
@@ -0,0 +1,2 @@ +-- @@stderr -- +dtrace: failed to compile script test/unittest/lexer/err.D_SYNTAX.scope-triple.d: [D_SYNTAX] line 17: syntax error near "foo```bar"
test/unittest/lexer/tst.scope-user-explicit.d new file +22 -0
@@ -0,0 +1,22 @@ +/* + * Oracle Linux DTrace. + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * Licensed under the Universal Permissive License v 1.0 as shown at + * http://oss.oracle.com/licenses/upl. + */ + +/* @@trigger: testprobe */ +/* @@runtest-opts: -e */ + +/* + * ASSERTION: Explicit userspace module scoping resolves as a userspace + * external symbol reference. + */ + +#pragma D option quiet + +BEGIN +{ + trace(&testprobe``main); + exit(0); +}
test/unittest/sizeof/err.D_IDENT_UNDEF.UnknownSymbol.d +1 -1
@@ -16,6 +16,6 @@ BEGIN { - printf("sizeof(`): %d\n", sizeof(`)); + printf("sizeof(`unknown_symbol): %d\n", sizeof(`unknown_symbol)); exit(0); }
test/unittest/sizeof/err.D_IDENT_UNDEF.UnknownSymbol.r +1 -1
@@ -1,2 +1,2 @@ -- @@stderr -- -dtrace: failed to compile script test/unittest/sizeof/err.D_IDENT_UNDEF.UnknownSymbol.d: [D_IDENT_UNDEF] line 19: failed to resolve `: Unknown symbol name +dtrace: failed to compile script test/unittest/sizeof/err.D_IDENT_UNDEF.UnknownSymbol.d: [D_IDENT_UNDEF] line 19: failed to resolve `unknown_symbol: Unknown symbol name
test/unittest/types/err.D_DECL_SCOPE.scopeop-enumerator.d new file +16 -0
@@ -0,0 +1,16 @@ +/* + * Oracle Linux DTrace. + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * Licensed under the Universal Permissive License v 1.0 as shown at + * http://oss.oracle.com/licenses/upl. + */ + +/* + * ASSERTION: D scoping operators are not permitted in enumerator names. + */ + +#pragma D option quiet + +enum scopeop_enum { + foo`bar +};
test/unittest/types/err.D_DECL_SCOPE.scopeop-enumerator.r new file +2 -0
@@ -0,0 +1,2 @@ +-- @@stderr -- +dtrace: failed to compile script test/unittest/types/err.D_DECL_SCOPE.scopeop-enumerator.d: [D_DECL_SCOPE] line 15: D scoping operator may not be used in an enumerator name (foo`bar)
test/unittest/types/err.D_DECL_SCOPE.scopeop-ident.d new file +19 -0
@@ -0,0 +1,19 @@ +/* + * Oracle Linux DTrace. + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * Licensed under the Universal Permissive License v 1.0 as shown at + * http://oss.oracle.com/licenses/upl. + */ + +/* + * ASSERTION: D scoping operators are not permitted in declaration names. + */ + +#pragma D option quiet + +int foo`bar; + +BEGIN +{ + exit(1); +}
test/unittest/types/err.D_DECL_SCOPE.scopeop-ident.r new file +2 -0
@@ -0,0 +1,2 @@ +-- @@stderr -- +dtrace: failed to compile script test/unittest/types/err.D_DECL_SCOPE.scopeop-ident.d: [D_DECL_SCOPE] line 14: D scoping operator may not be used in a declaration name (foo`bar)
test/unittest/types/err.D_DECL_SCOPE.scopeop-member.d new file +16 -0
@@ -0,0 +1,16 @@ +/* + * Oracle Linux DTrace. + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * Licensed under the Universal Permissive License v 1.0 as shown at + * http://oss.oracle.com/licenses/upl. + */ + +/* + * ASSERTION: D scoping operators are not permitted in struct member names. + */ + +#pragma D option quiet + +struct scopeop_struct { + int foo`bar; +};
test/unittest/types/err.D_DECL_SCOPE.scopeop-member.r new file +2 -0
@@ -0,0 +1,2 @@ +-- @@stderr -- +dtrace: failed to compile script test/unittest/types/err.D_DECL_SCOPE.scopeop-member.d: [D_DECL_SCOPE] line 15: D scoping operator may not be used in a member name (foo`bar)
Signature · 1 line
2.47.3