Skip to content

Commit 09a15fd

Browse files
fix(namer): escape, rather than strip, non-ASCII ident. characters
Escape non-ASCII identifier characters with `write!(…, "u{:04x}", …)`, surrounding with `_` as appropriate. This solves (1) a debugging issue where stripped characters would otherwise be invisible, and (2) failure to re-validate that stripped identifiers didn't start with an ASCII digit. I've confirmed that this fixes [bug 1978197](https://bugzilla.mozilla.org/show_bug.cgi?id=1978197) on the Firefox side.
1 parent eefd6e8 commit 09a15fd

34 files changed

+264
-110
lines changed

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ Naga now requires that no type be larger than 1 GB. This limit may be lowered in
6767
- Fixed build error occurring when the `profiling` dependency is configured to have profiling active. By @kpreid in [#7916](https://github.com/gfx-rs/wgpu/pull/7916).
6868
- Emit a validation error instead of panicking when a query set index is OOB. By @ErichDonGubler in [#7908](https://github.com/gfx-rs/wgpu/pull/7908).
6969

70+
#### Naga
71+
72+
- Escape, rather than strip, identifiers with Unicode. By @ErichDonGubler in [7995](https://github.com/gfx-rs/wgpu/pull/7995).
73+
7074
## v26.0.0 (2025-07-09)
7175

7276
### Major Features
@@ -209,7 +213,6 @@ By @Vecvec in [#7829](https://github.com/gfx-rs/wgpu/pull/7829).
209213
- The definition of `enum CommandEncoderError` has changed significantly, to reflect which errors can be raised by `CommandEncoder.finish()`. There are also some errors that no longer appear directly in `CommandEncoderError`, and instead appear nested within the `RenderPass` or `ComputePass` variants.
210214
- `CopyError` has been removed. Errors that were previously a `CopyError` are now a `CommandEncoderError` returned by `finish()`. (The detailed reasons for copies to fail were and still are described by `TransferError`, which was previously a variant of `CopyError`, and is now a variant of `CommandEncoderError`).
211215

212-
213216
#### Naga
214217

215218
- Mark `readonly_and_readwrite_storage_textures` & `packed_4x8_integer_dot_product` language extensions as implemented. By @teoxoy in [#7543](https://github.com/gfx-rs/wgpu/pull/7543)

naga/src/proc/namer.rs

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -86,20 +86,31 @@ impl Namer {
8686
{
8787
Cow::Borrowed(string)
8888
} else {
89-
let mut filtered = string
90-
.chars()
91-
.filter(|&c| c.is_ascii_alphanumeric() || c == '_')
92-
.fold(String::new(), |mut s, c| {
93-
if s.ends_with('_') && c == '_' {
94-
return s;
95-
}
89+
let mut filtered = string.chars().fold(String::new(), |mut s, c| {
90+
let had_underscore_at_end = s.ends_with('_');
91+
if had_underscore_at_end && c == '_' {
92+
return s;
93+
}
94+
if c.is_ascii_alphanumeric() || c == '_' {
9695
s.push(c);
97-
s
98-
});
96+
} else {
97+
use core::fmt::Write as _;
98+
if !s.is_empty() && !had_underscore_at_end {
99+
s.push('_');
100+
}
101+
write!(s, "u{:04x}_", c as u32).unwrap();
102+
}
103+
s
104+
});
99105
let stripped_len = filtered.trim_end_matches(SEPARATOR).len();
100106
filtered.truncate(stripped_len);
101107
if filtered.is_empty() {
102108
filtered.push_str("unnamed");
109+
} else if filtered.starts_with(|c: char| c.is_ascii_digit()) {
110+
unreachable!(
111+
"internal error: invalid identifier starting with ASCII digit {:?}",
112+
filtered.chars().nth(0)
113+
)
103114
}
104115
Cow::Owned(filtered)
105116
};
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// NOTE: This allows us to suppress compaction below, to force the handling of identifiers
2+
// containing Unicode.
3+
@group(0) @binding(0)
4+
var<storage> asdf: f32;
5+
6+
fn compute() -> f32 {
7+
let θ2 = asdf + 9001.0;
8+
return θ2;
9+
}
10+
11+
@compute @workgroup_size(1, 1)
12+
fn main() {
13+
compute();
14+
}

naga/tests/out/glsl/spv-do-while.main.Fragment.glsl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ precision highp float;
44
precision highp int;
55

66

7-
void fb1_(inout bool cond) {
7+
void f_u0028_b1_u003b(inout bool cond) {
88
bool loop_init = true;
99
while(true) {
1010
if (!loop_init) {
@@ -22,7 +22,7 @@ void fb1_(inout bool cond) {
2222
void main_1() {
2323
bool param = false;
2424
param = false;
25-
fb1_(param);
25+
f_u0028_b1_u003b(param);
2626
return;
2727
}
2828

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#version 310 es
2+
3+
precision highp float;
4+
precision highp int;
5+
6+
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
7+
8+
layout(std430) readonly buffer type_block_0Compute { float _group_0_binding_0_cs; };
9+
10+
11+
float compute() {
12+
float _e1 = _group_0_binding_0_cs;
13+
float u03b8_2_ = (_e1 + 9001.0);
14+
return u03b8_2_;
15+
}
16+
17+
void main() {
18+
float _e0 = compute();
19+
return;
20+
}
21+

naga/tests/out/glsl/wgsl-atomicCompareExchange.test_atomic_compare_exchange_i32.Compute.glsl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ precision highp int;
55

66
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
77

8-
struct _atomic_compare_exchange_resultSint4_ {
8+
struct _atomic_compare_exchange_result_u003c_Sint_u002c_4_u003e {
99
int old_value;
1010
bool exchanged;
1111
};
12-
struct _atomic_compare_exchange_resultUint4_ {
12+
struct _atomic_compare_exchange_result_u003c_Uint_u002c_4_u003e {
1313
uint old_value;
1414
bool exchanged;
1515
};
@@ -50,7 +50,7 @@ void main() {
5050
int new = floatBitsToInt((intBitsToFloat(_e14) + 1.0));
5151
uint _e20 = i;
5252
int _e22 = old;
53-
_atomic_compare_exchange_resultSint4_ _e23; _e23.old_value = atomicCompSwap(_group_0_binding_0_cs[_e20], _e22, new);
53+
_atomic_compare_exchange_result_u003c_Sint_u002c_4_u003e _e23; _e23.old_value = atomicCompSwap(_group_0_binding_0_cs[_e20], _e22, new);
5454
_e23.exchanged = (_e23.old_value == _e22);
5555
old = _e23.old_value;
5656
exchanged = _e23.exchanged;

naga/tests/out/glsl/wgsl-atomicCompareExchange.test_atomic_compare_exchange_u32.Compute.glsl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ precision highp int;
55

66
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
77

8-
struct _atomic_compare_exchange_resultSint4_ {
8+
struct _atomic_compare_exchange_result_u003c_Sint_u002c_4_u003e {
99
int old_value;
1010
bool exchanged;
1111
};
12-
struct _atomic_compare_exchange_resultUint4_ {
12+
struct _atomic_compare_exchange_result_u003c_Uint_u002c_4_u003e {
1313
uint old_value;
1414
bool exchanged;
1515
};
@@ -50,7 +50,7 @@ void main() {
5050
uint new = floatBitsToUint((uintBitsToFloat(_e14) + 1.0));
5151
uint _e20 = i_1;
5252
uint _e22 = old_1;
53-
_atomic_compare_exchange_resultUint4_ _e23; _e23.old_value = atomicCompSwap(_group_0_binding_1_cs[_e20], _e22, new);
53+
_atomic_compare_exchange_result_u003c_Uint_u002c_4_u003e _e23; _e23.old_value = atomicCompSwap(_group_0_binding_1_cs[_e20], _e22, new);
5454
_e23.exchanged = (_e23.old_value == _e22);
5555
old_1 = _e23.old_value;
5656
exchanged_1 = _e23.exchanged;

naga/tests/out/glsl/wgsl-atomicOps.cs_main.Compute.glsl

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ struct Struct {
99
uint atomic_scalar;
1010
int atomic_arr[2];
1111
};
12-
struct _atomic_compare_exchange_resultUint4_ {
12+
struct _atomic_compare_exchange_result_u003c_Uint_u002c_4_u003e {
1313
uint old_value;
1414
bool exchanged;
1515
};
16-
struct _atomic_compare_exchange_resultSint4_ {
16+
struct _atomic_compare_exchange_result_u003c_Sint_u002c_4_u003e {
1717
int old_value;
1818
bool exchanged;
1919
};
@@ -135,21 +135,21 @@ void main() {
135135
int _e295 = atomicExchange(workgroup_atomic_arr[1], 1);
136136
uint _e299 = atomicExchange(workgroup_struct.atomic_scalar, 1u);
137137
int _e304 = atomicExchange(workgroup_struct.atomic_arr[1], 1);
138-
_atomic_compare_exchange_resultUint4_ _e308; _e308.old_value = atomicCompSwap(_group_0_binding_0_cs, 1u, 2u);
138+
_atomic_compare_exchange_result_u003c_Uint_u002c_4_u003e _e308; _e308.old_value = atomicCompSwap(_group_0_binding_0_cs, 1u, 2u);
139139
_e308.exchanged = (_e308.old_value == 1u);
140-
_atomic_compare_exchange_resultSint4_ _e313; _e313.old_value = atomicCompSwap(_group_0_binding_1_cs[1], 1, 2);
140+
_atomic_compare_exchange_result_u003c_Sint_u002c_4_u003e _e313; _e313.old_value = atomicCompSwap(_group_0_binding_1_cs[1], 1, 2);
141141
_e313.exchanged = (_e313.old_value == 1);
142-
_atomic_compare_exchange_resultUint4_ _e318; _e318.old_value = atomicCompSwap(_group_0_binding_2_cs.atomic_scalar, 1u, 2u);
142+
_atomic_compare_exchange_result_u003c_Uint_u002c_4_u003e _e318; _e318.old_value = atomicCompSwap(_group_0_binding_2_cs.atomic_scalar, 1u, 2u);
143143
_e318.exchanged = (_e318.old_value == 1u);
144-
_atomic_compare_exchange_resultSint4_ _e324; _e324.old_value = atomicCompSwap(_group_0_binding_2_cs.atomic_arr[1], 1, 2);
144+
_atomic_compare_exchange_result_u003c_Sint_u002c_4_u003e _e324; _e324.old_value = atomicCompSwap(_group_0_binding_2_cs.atomic_arr[1], 1, 2);
145145
_e324.exchanged = (_e324.old_value == 1);
146-
_atomic_compare_exchange_resultUint4_ _e328; _e328.old_value = atomicCompSwap(workgroup_atomic_scalar, 1u, 2u);
146+
_atomic_compare_exchange_result_u003c_Uint_u002c_4_u003e _e328; _e328.old_value = atomicCompSwap(workgroup_atomic_scalar, 1u, 2u);
147147
_e328.exchanged = (_e328.old_value == 1u);
148-
_atomic_compare_exchange_resultSint4_ _e333; _e333.old_value = atomicCompSwap(workgroup_atomic_arr[1], 1, 2);
148+
_atomic_compare_exchange_result_u003c_Sint_u002c_4_u003e _e333; _e333.old_value = atomicCompSwap(workgroup_atomic_arr[1], 1, 2);
149149
_e333.exchanged = (_e333.old_value == 1);
150-
_atomic_compare_exchange_resultUint4_ _e338; _e338.old_value = atomicCompSwap(workgroup_struct.atomic_scalar, 1u, 2u);
150+
_atomic_compare_exchange_result_u003c_Uint_u002c_4_u003e _e338; _e338.old_value = atomicCompSwap(workgroup_struct.atomic_scalar, 1u, 2u);
151151
_e338.exchanged = (_e338.old_value == 1u);
152-
_atomic_compare_exchange_resultSint4_ _e344; _e344.old_value = atomicCompSwap(workgroup_struct.atomic_arr[1], 1, 2);
152+
_atomic_compare_exchange_result_u003c_Sint_u002c_4_u003e _e344; _e344.old_value = atomicCompSwap(workgroup_struct.atomic_arr[1], 1, 2);
153153
_e344.exchanged = (_e344.old_value == 1);
154154
return;
155155
}

naga/tests/out/hlsl/spv-do-while.hlsl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
void fb1_(inout bool cond)
1+
void f_u0028_b1_u003b(inout bool cond)
22
{
33
uint2 loop_bound = uint2(4294967295u, 4294967295u);
44
bool loop_init = true;
@@ -22,7 +22,7 @@ void main_1()
2222
bool param = (bool)0;
2323

2424
param = false;
25-
fb1_(param);
25+
f_u0028_b1_u003b(param);
2626
return;
2727
}
2828

naga/tests/out/hlsl/spv-fetch_depth.hlsl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ void function()
1919
}
2020

2121
[numthreads(32, 1, 1)]
22-
void cullfetch_depth()
22+
void cull_u003a_u003a_fetch_depth()
2323
{
2424
function();
2525
}

0 commit comments

Comments
 (0)