From alan.maguire at oracle.com Fri Sep 11 14:32:12 2026 From: alan.maguire at oracle.com (Alan Maguire) Date: Fri, 11 Sep 2026 15:32:12 +0100 Subject: [DTrace-devel] [PATCH] parser: validate scoped external names In-Reply-To: <5de2ae24696627e3c3b28afc4a49e51f@oracle.com> References: <5de2ae24696627e3c3b28afc4a49e51f@oracle.com> Message-ID: On 28/08/2026 19:48, Kris Van Hees via DTrace-devel wrote: > 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. > > Signed-off-by: Kris Van Hees One AI-assisted issue found here I think; D allows us to scope type references IIRC; i.e. struct vmlinux`task_struct *task; or sizeof(struct vmlinux`task_struct) However the backtick support here also allows a backtick in local type declarations which doesn't make sense: struct vmlinux`task_struct { int replacement; }; We can likely distinguish type declaration (no ` allowed) from scoped variable declaration in dt_decl_sou()/dt_decl_enum() but I think we need to do so. > --- > 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 > > diff --git a/libdtrace/dt_decl.c b/libdtrace/dt_decl.c > index 1f4936dd..68999422 100644 > --- a/libdtrace/dt_decl.c > +++ b/libdtrace/dt_decl.c > @@ -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); > } > diff --git a/libdtrace/dt_lex.l b/libdtrace/dt_lex.l > index fd70aa0a..bf133676 100644 > --- a/libdtrace/dt_lex.l > +++ b/libdtrace/dt_lex.l > @@ -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; > } > > +{RGX_SCOPE_IDENT} | > {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); > > diff --git a/libdtrace/dt_parser.c b/libdtrace/dt_parser.c > index e71c0985..1fd0f5b4 100644 > --- a/libdtrace/dt_parser.c > +++ b/libdtrace/dt_parser.c > @@ -168,45 +168,96 @@ opstr(int op) > } > } > > +/* > + * Parse the D scoping mark used in external type and symbol names. A scoped > + * name can contain one mark only: ` for kernel scope, or `` for user scope. > + * Longer runs and repeated marks are malformed. Return the scope kind as 0 > + * for no scope, 1 for kernel scope, or 2 for user scope. > + */ > int > -dt_type_lookup(const char *s, dtrace_typeinfo_t *tip) > +dt_scope_parse(const char *s, const char **scopep, const char **identp) > { > - static const char delimiters[] = " \t\n\r\v\f*`"; > - dtrace_hdl_t *dtp = yypcb->pcb_hdl; > - const char *p, *q, *end, *obj; > + static const char delimiters[] = " \t\n\r\v\f*"; > + const char *mark = strchr(s, '`'); > + const char *scope; > + size_t marklen = 1; > + > + if (mark == NULL) { > + if (scopep != NULL) > + *scopep = DTRACE_OBJ_EXEC; > + if (identp != NULL) > + *identp = s; > + return 0; > + } > > - for (p = s, end = s + strlen(s); *p != '\0'; p = q) { > - while (isspace(*p)) > - p++; /* skip leading whitespace prior to token */ > + if (mark[1] == '`') { > + marklen = 2; > + if (mark[2] == '`') > + return -1; > + } > > - if (p == end || (q = strpbrk(p + 1, delimiters)) == NULL) > - break; /* empty string or single token remaining */ > + if (mark[marklen] == '\0') > + return -1; > > - if (*q == '`') { > - char *object = alloca((size_t)(q - p) + 1); > - char *type = alloca((size_t)(end - s) + 1); > + if (strchr(mark + marklen, '`') != NULL) > + return -1; > > - /* > - * Copy from the start of the token (p) to the location > - * backquote (q) to extract the nul-terminated object. > - */ > - memcpy(object, p, (size_t)(q - p)); > - object[(size_t)(q - p)] = '\0'; > + for (scope = mark; > + scope > s && strchr(delimiters, scope[-1]) == NULL; ) > + scope--; > > - /* > - * Copy the original string up to the start of this > - * token (p) into type, and then concatenate everything > - * after q. This is the type name without the object. > - */ > - memcpy(type, s, (size_t)(p - s)); > - memcpy(type + (size_t)(p - s), q + 1, > - strlen(q + 1) + 1); > + if (scope == mark) > + scope = marklen == 2 ? DTRACE_OBJ_UMODS : DTRACE_OBJ_KMODS; > + > + if (scopep != NULL) > + *scopep = scope; > + if (identp != NULL) > + *identp = mark + marklen; > + > + return marklen; > +} > + > +int > +dt_type_lookup(const char *s, dtrace_typeinfo_t *tip) > +{ > + dtrace_hdl_t *dtp = yypcb->pcb_hdl; > + const char *scope, *ident, *start, *obj; > + int scopekind; > + > + scopekind = dt_scope_parse(s, &scope, &ident); > + if (scopekind < 0) > + return dt_set_errno(dtp, EDT_BADSCOPE); > > - if (strchr(q + 1, '`') != NULL) > - return dt_set_errno(dtp, EDT_BADSCOPE); > + if (scopekind > 0) { > + char *type; > + > + /* > + * If there is no explicit object before the mark, search all > + * kernel or user objects depending on the mark width. > + */ > + if (scope == DTRACE_OBJ_KMODS || scope == DTRACE_OBJ_UMODS) { > + start = ident - scopekind; > + obj = scope; > + } else { > + size_t objlen = (size_t)(ident - scope) - scopekind; > + char *object = alloca(objlen + 1); > > - return dtrace_lookup_by_type(dtp, object, type, tip); > + memcpy(object, scope, objlen); > + object[objlen] = '\0'; > + start = scope; > + obj = object; > } > + > + /* > + * Copy the original string up to the start of this token > + * into type, and then concatenate everything after the scoping > + * mark. This is the type name without the object and mark. > + */ > + type = alloca((size_t)(start - s) + strlen(ident) + 1); > + memcpy(type, s, (size_t)(start - s)); > + memcpy(type + (size_t)(start - s), ident, strlen(ident) + 1); > + > + return dtrace_lookup_by_type(dtp, obj, type, tip); > } > > if (yypcb->pcb_idepth != 0) > @@ -2767,9 +2818,10 @@ dt_xcook_ident(dt_node_t *dnp, dt_idhash_t *dhp, uint_t idkind, int create) > dtrace_syminfo_t dts; > GElf_Sym sym; > > - const char *scope, *mark; > + const char *scope, *ident, *markstr; > uchar_t dnkind; > char *name; > + int scopekind; > > /* > * Look for scoping marks in the identifier. If one is found, set our > @@ -2779,18 +2831,16 @@ dt_xcook_ident(dt_node_t *dnp, dt_idhash_t *dhp, uint_t idkind, int create) > * Otherwise we set scope to DTRACE_OBJ_EXEC, indicating that normal > * scope is desired and we should search the specified idhash. > */ > - if ((name = strrchr(dnp->dn_string, '`')) != NULL) { > - if (name > dnp->dn_string && name[-1] == '`') { > - uref++; > - name[-1] = '\0'; > - } > - > - if (name == dnp->dn_string + uref) > - scope = uref ? DTRACE_OBJ_UMODS : DTRACE_OBJ_KMODS; > - else > - scope = dnp->dn_string; > + scopekind = dt_scope_parse(dnp->dn_string, &scope, &ident); > + if (scopekind < 0) { > + xyerror(D_SYNTAX, "syntax error near \"%s\"\n", > + dnp->dn_string); > + } > > - *name++ = '\0'; /* leave name pointing after scoping mark */ > + if (scopekind > 0) { > + uref = scopekind == 2; > + name = (char *)ident; > + *(char *)(ident - scopekind) = '\0'; > dnkind = DT_NODE_VAR; > > } else if (idkind == DT_IDENT_AGG) { > @@ -2810,7 +2860,7 @@ dt_xcook_ident(dt_node_t *dnp, dt_idhash_t *dhp, uint_t idkind, int create) > * errno appropriately and that error will be reported instead. > */ > dt_set_errno(dtp, EDT_NOVAR); > - mark = uref ? "``" : "`"; > + markstr = uref ? "``" : "`"; > > if (scope == DTRACE_OBJ_EXEC && ( > (dhp != dtp->dt_globals && > @@ -2902,13 +2952,13 @@ dt_xcook_ident(dt_node_t *dnp, dt_idhash_t *dhp, uint_t idkind, int create) > xyerror(D_SYM_MODEL, "cannot use %s symbol " > "%s%s%s in a %s D program\n", > dt_module_modelname(mp), dts.object, > - mark, dts.name, > + markstr, dts.name, > dt_module_modelname(dtp->dt_ddefs)); > } > > xyerror(D_SYM_NOTYPES, "no symbolic type information " > "is available for %s%s%s: %s\n", > - dts.object, mark, dts.name, > + dts.object, markstr, dts.name, > dtrace_errmsg(dtp, dtrace_errno(dtp))); > } > > @@ -3014,7 +3064,7 @@ dt_xcook_ident(dt_node_t *dnp, dt_idhash_t *dhp, uint_t idkind, int create) > > } else if (scope != DTRACE_OBJ_EXEC) { > xyerror(D_IDENT_UNDEF, "failed to resolve %s%s%s: %s\n", > - dnp->dn_string, mark, name, > + dnp->dn_string, markstr, name, > dtrace_errmsg(dtp, dtrace_errno(dtp))); > } else { > xyerror(D_IDENT_UNDEF, "failed to resolve %s: %s\n", > diff --git a/libdtrace/dt_parser.h b/libdtrace/dt_parser.h > index d74d658a..b9149220 100644 > --- a/libdtrace/dt_parser.h > +++ b/libdtrace/dt_parser.h > @@ -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 *); > diff --git a/test/unittest/lexer/err.D_IDENT_UNDEF.scope-dot-kernel.d b/test/unittest/lexer/err.D_IDENT_UNDEF.scope-dot-kernel.d > new file mode 100644 > index 00000000..2a267567 > --- /dev/null > +++ b/test/unittest/lexer/err.D_IDENT_UNDEF.scope-dot-kernel.d > @@ -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); > +} > diff --git a/test/unittest/lexer/err.D_IDENT_UNDEF.scope-dot-kernel.r b/test/unittest/lexer/err.D_IDENT_UNDEF.scope-dot-kernel.r > new file mode 100644 > index 00000000..89a9f9c5 > --- /dev/null > +++ b/test/unittest/lexer/err.D_IDENT_UNDEF.scope-dot-kernel.r > @@ -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 > diff --git a/test/unittest/lexer/err.D_IDENT_UNDEF.scope-dot.d b/test/unittest/lexer/err.D_IDENT_UNDEF.scope-dot.d > new file mode 100644 > index 00000000..6b3dcfda > --- /dev/null > +++ b/test/unittest/lexer/err.D_IDENT_UNDEF.scope-dot.d > @@ -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); > +} > diff --git a/test/unittest/lexer/err.D_IDENT_UNDEF.scope-dot.r b/test/unittest/lexer/err.D_IDENT_UNDEF.scope-dot.r > new file mode 100644 > index 00000000..7734e29f > --- /dev/null > +++ b/test/unittest/lexer/err.D_IDENT_UNDEF.scope-dot.r > @@ -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 > diff --git a/test/unittest/lexer/err.D_SYM_BADREF.scope-kernel-as-user.d b/test/unittest/lexer/err.D_SYM_BADREF.scope-kernel-as-user.d > new file mode 100644 > index 00000000..d332191b > --- /dev/null > +++ b/test/unittest/lexer/err.D_SYM_BADREF.scope-kernel-as-user.d > @@ -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); > +} > diff --git a/test/unittest/lexer/err.D_SYM_BADREF.scope-kernel-as-user.r b/test/unittest/lexer/err.D_SYM_BADREF.scope-kernel-as-user.r > new file mode 100644 > index 00000000..718b2b31 > --- /dev/null > +++ b/test/unittest/lexer/err.D_SYM_BADREF.scope-kernel-as-user.r > @@ -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 > diff --git a/test/unittest/lexer/err.D_SYM_BADREF.scope-user-as-kernel.d b/test/unittest/lexer/err.D_SYM_BADREF.scope-user-as-kernel.d > new file mode 100644 > index 00000000..bc7e8b9f > --- /dev/null > +++ b/test/unittest/lexer/err.D_SYM_BADREF.scope-user-as-kernel.d > @@ -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); > +} > diff --git a/test/unittest/lexer/err.D_SYM_BADREF.scope-user-as-kernel.r b/test/unittest/lexer/err.D_SYM_BADREF.scope-user-as-kernel.r > new file mode 100644 > index 00000000..87169597 > --- /dev/null > +++ b/test/unittest/lexer/err.D_SYM_BADREF.scope-user-as-kernel.r > @@ -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 > diff --git a/test/unittest/lexer/err.D_SYNTAX.scope-empty-bare-user.d b/test/unittest/lexer/err.D_SYNTAX.scope-empty-bare-user.d > new file mode 100644 > index 00000000..d7cff89f > --- /dev/null > +++ b/test/unittest/lexer/err.D_SYNTAX.scope-empty-bare-user.d > @@ -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); > +} > diff --git a/test/unittest/lexer/err.D_SYNTAX.scope-empty-bare-user.r b/test/unittest/lexer/err.D_SYNTAX.scope-empty-bare-user.r > new file mode 100644 > index 00000000..8e9cd1ff > --- /dev/null > +++ b/test/unittest/lexer/err.D_SYNTAX.scope-empty-bare-user.r > @@ -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 "``" > diff --git a/test/unittest/lexer/err.D_SYNTAX.scope-empty-bare.d b/test/unittest/lexer/err.D_SYNTAX.scope-empty-bare.d > new file mode 100644 > index 00000000..44b4f60e > --- /dev/null > +++ b/test/unittest/lexer/err.D_SYNTAX.scope-empty-bare.d > @@ -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); > +} > diff --git a/test/unittest/lexer/err.D_SYNTAX.scope-empty-bare.r b/test/unittest/lexer/err.D_SYNTAX.scope-empty-bare.r > new file mode 100644 > index 00000000..bbba5fe8 > --- /dev/null > +++ b/test/unittest/lexer/err.D_SYNTAX.scope-empty-bare.r > @@ -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 "`" > diff --git a/test/unittest/lexer/err.D_SYNTAX.scope-empty-dot-user.d b/test/unittest/lexer/err.D_SYNTAX.scope-empty-dot-user.d > new file mode 100644 > index 00000000..5ead7b3e > --- /dev/null > +++ b/test/unittest/lexer/err.D_SYNTAX.scope-empty-dot-user.d > @@ -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); > +} > diff --git a/test/unittest/lexer/err.D_SYNTAX.scope-empty-dot-user.r b/test/unittest/lexer/err.D_SYNTAX.scope-empty-dot-user.r > new file mode 100644 > index 00000000..b07c07b1 > --- /dev/null > +++ b/test/unittest/lexer/err.D_SYNTAX.scope-empty-dot-user.r > @@ -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``" > diff --git a/test/unittest/lexer/err.D_SYNTAX.scope-empty-user.d b/test/unittest/lexer/err.D_SYNTAX.scope-empty-user.d > new file mode 100644 > index 00000000..d3a927d7 > --- /dev/null > +++ b/test/unittest/lexer/err.D_SYNTAX.scope-empty-user.d > @@ -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); > +} > diff --git a/test/unittest/lexer/err.D_SYNTAX.scope-empty-user.r b/test/unittest/lexer/err.D_SYNTAX.scope-empty-user.r > new file mode 100644 > index 00000000..dbf319ea > --- /dev/null > +++ b/test/unittest/lexer/err.D_SYNTAX.scope-empty-user.r > @@ -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``" > diff --git a/test/unittest/lexer/err.D_SYNTAX.scope-empty.d b/test/unittest/lexer/err.D_SYNTAX.scope-empty.d > new file mode 100644 > index 00000000..e32b3812 > --- /dev/null > +++ b/test/unittest/lexer/err.D_SYNTAX.scope-empty.d > @@ -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); > +} > diff --git a/test/unittest/lexer/err.D_SYNTAX.scope-empty.r b/test/unittest/lexer/err.D_SYNTAX.scope-empty.r > new file mode 100644 > index 00000000..d78728b2 > --- /dev/null > +++ b/test/unittest/lexer/err.D_SYNTAX.scope-empty.r > @@ -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`" > diff --git a/test/unittest/lexer/err.D_SYNTAX.scope-multiple.d b/test/unittest/lexer/err.D_SYNTAX.scope-multiple.d > new file mode 100644 > index 00000000..5e236c45 > --- /dev/null > +++ b/test/unittest/lexer/err.D_SYNTAX.scope-multiple.d > @@ -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); > +} > diff --git a/test/unittest/lexer/err.D_SYNTAX.scope-multiple.r b/test/unittest/lexer/err.D_SYNTAX.scope-multiple.r > new file mode 100644 > index 00000000..cefc56ad > --- /dev/null > +++ b/test/unittest/lexer/err.D_SYNTAX.scope-multiple.r > @@ -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" > diff --git a/test/unittest/lexer/err.D_SYNTAX.scope-triple.d b/test/unittest/lexer/err.D_SYNTAX.scope-triple.d > new file mode 100644 > index 00000000..41f7391c > --- /dev/null > +++ b/test/unittest/lexer/err.D_SYNTAX.scope-triple.d > @@ -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); > +} > diff --git a/test/unittest/lexer/err.D_SYNTAX.scope-triple.r b/test/unittest/lexer/err.D_SYNTAX.scope-triple.r > new file mode 100644 > index 00000000..4474c502 > --- /dev/null > +++ b/test/unittest/lexer/err.D_SYNTAX.scope-triple.r > @@ -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" > diff --git a/test/unittest/lexer/tst.scope-user-explicit.d b/test/unittest/lexer/tst.scope-user-explicit.d > new file mode 100644 > index 00000000..2d649f6f > --- /dev/null > +++ b/test/unittest/lexer/tst.scope-user-explicit.d > @@ -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); > +} > diff --git a/test/unittest/sizeof/err.D_IDENT_UNDEF.UnknownSymbol.d b/test/unittest/sizeof/err.D_IDENT_UNDEF.UnknownSymbol.d > index 56c93d43..4de9322d 100644 > --- a/test/unittest/sizeof/err.D_IDENT_UNDEF.UnknownSymbol.d > +++ b/test/unittest/sizeof/err.D_IDENT_UNDEF.UnknownSymbol.d > @@ -16,6 +16,6 @@ > > BEGIN > { > - printf("sizeof(`): %d\n", sizeof(`)); > + printf("sizeof(`unknown_symbol): %d\n", sizeof(`unknown_symbol)); > exit(0); > } > diff --git a/test/unittest/sizeof/err.D_IDENT_UNDEF.UnknownSymbol.r b/test/unittest/sizeof/err.D_IDENT_UNDEF.UnknownSymbol.r > index 462469b7..0f46ad1e 100644 > --- a/test/unittest/sizeof/err.D_IDENT_UNDEF.UnknownSymbol.r > +++ b/test/unittest/sizeof/err.D_IDENT_UNDEF.UnknownSymbol.r > @@ -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 > diff --git a/test/unittest/types/err.D_DECL_SCOPE.scopeop-enumerator.d b/test/unittest/types/err.D_DECL_SCOPE.scopeop-enumerator.d > new file mode 100644 > index 00000000..51068c20 > --- /dev/null > +++ b/test/unittest/types/err.D_DECL_SCOPE.scopeop-enumerator.d > @@ -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 > +}; > diff --git a/test/unittest/types/err.D_DECL_SCOPE.scopeop-enumerator.r b/test/unittest/types/err.D_DECL_SCOPE.scopeop-enumerator.r > new file mode 100644 > index 00000000..06ef912b > --- /dev/null > +++ b/test/unittest/types/err.D_DECL_SCOPE.scopeop-enumerator.r > @@ -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) > diff --git a/test/unittest/types/err.D_DECL_SCOPE.scopeop-ident.d b/test/unittest/types/err.D_DECL_SCOPE.scopeop-ident.d > new file mode 100644 > index 00000000..6042e208 > --- /dev/null > +++ b/test/unittest/types/err.D_DECL_SCOPE.scopeop-ident.d > @@ -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); > +} > diff --git a/test/unittest/types/err.D_DECL_SCOPE.scopeop-ident.r b/test/unittest/types/err.D_DECL_SCOPE.scopeop-ident.r > new file mode 100644 > index 00000000..7b2e6797 > --- /dev/null > +++ b/test/unittest/types/err.D_DECL_SCOPE.scopeop-ident.r > @@ -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) > diff --git a/test/unittest/types/err.D_DECL_SCOPE.scopeop-member.d b/test/unittest/types/err.D_DECL_SCOPE.scopeop-member.d > new file mode 100644 > index 00000000..5fe36a00 > --- /dev/null > +++ b/test/unittest/types/err.D_DECL_SCOPE.scopeop-member.d > @@ -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; > +}; > diff --git a/test/unittest/types/err.D_DECL_SCOPE.scopeop-member.r b/test/unittest/types/err.D_DECL_SCOPE.scopeop-member.r > new file mode 100644 > index 00000000..978ef79d > --- /dev/null > +++ b/test/unittest/types/err.D_DECL_SCOPE.scopeop-member.r > @@ -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) > -- > 2.52.0 > > > _______________________________________________ > DTrace-devel mailing list > DTrace-devel at oss.oracle.com > https://oss.oracle.com/mailman/listinfo/dtrace-devel >