Skip to content

Commit cd689ef

Browse files
committed
internal/core/adt: fix panic triggered by using wrong condition
Use the isInitialized() instead of the corresponding flag in nodeContext: a finalized node, may currently still have an uninitialized nodeContext. This bug was exposed by a code path that is itself exposing a bug. We add tests for this, but also add a test case that is not erroneous, but exposes this code path so that this fix will remain tested even if the triggering bug is fixed. Fixes #3330 Signed-off-by: Marcel van Lohuizen <[email protected]> Change-Id: Ibe7d130bf66a22b14df7dd4012fd346649280419 Reviewed-on: https://cue.gerrithub.io/c/cue-lang/cue/+/1198860 Unity-Result: CUE porcuepine <[email protected]> Reviewed-by: Daniel Martí <[email protected]> TryBot-Result: CUEcueckoo <[email protected]>
1 parent cf18d6f commit cd689ef

File tree

4 files changed

+395
-2
lines changed

4 files changed

+395
-2
lines changed

cue/testdata/eval/issue3330.txtar

Lines changed: 391 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,391 @@
1+
-- in.cue --
2+
import "list"
3+
4+
issue3330: {
5+
#A: {
6+
let empty = {}
7+
8+
// Reference to empty is within the definition that defines it. Closedness
9+
// thus does not trigger.
10+
field: null | { n: int }
11+
field: empty & { n: 3 }
12+
}
13+
14+
out: list.Concat([[#A]])
15+
}
16+
17+
eliminated: {
18+
// This test case ensures a definition is only used for the empty struct.
19+
// This ensures that the elimination of disjuncts is triggered, ensuring
20+
// the code path that caused the panic in issue3330 is triggered even when
21+
// the closedness bug that triggered it indirectly is fixed.
22+
#empty: {}
23+
x: null | { n: 3 }
24+
x: #empty & { n: 3 }
25+
out: len(x)
26+
}
27+
28+
simplified: {
29+
// This is a different take on the above bug that demonstrates the issue
30+
// is only triggered after a definition is referenced.
31+
#struct: {
32+
field: { n: 3 } & g
33+
g: {}
34+
}
35+
36+
out: #struct & {}
37+
}
38+
-- out/eval/stats --
39+
Leaks: 0
40+
Freed: 51
41+
Reused: 42
42+
Allocs: 9
43+
Retain: 3
44+
45+
Unifications: 41
46+
Conjuncts: 83
47+
Disjuncts: 54
48+
-- out/evalalpha --
49+
Errors:
50+
eliminated.x: conflicting values null and {} (mismatched types null and struct):
51+
./in.cue:21:10
52+
./in.cue:22:5
53+
issue3330.0.0.field: conflicting values null and {} (mismatched types null and struct):
54+
./in.cue:5:15
55+
./in.cue:9:10
56+
issue3330.0.0.field.n: field not allowed:
57+
./in.cue:10:10
58+
./in.cue:10:20
59+
eliminated.x.n: field not allowed:
60+
./in.cue:23:5
61+
./in.cue:23:16
62+
simplified.out.field.n: field not allowed:
63+
./in.cue:31:21
64+
./in.cue:31:12
65+
66+
Result:
67+
(_|_){
68+
// [eval]
69+
issue3330: (_|_){
70+
// [eval]
71+
#A: (#struct){
72+
let empty#1 = (#struct){
73+
}
74+
field: (#struct){
75+
n: (int){ 3 }
76+
}
77+
}
78+
out: (_|_){
79+
// [eval] issue3330.0.0.field: conflicting values null and {} (mismatched types null and struct):
80+
// ./in.cue:5:15
81+
// ./in.cue:9:10
82+
// issue3330.0.0.field.n: field not allowed:
83+
// ./in.cue:10:10
84+
// ./in.cue:10:20
85+
}
86+
}
87+
eliminated: (_|_){
88+
// [eval]
89+
#empty: (#struct){
90+
}
91+
x: (_|_){
92+
// [eval] eliminated.x: conflicting values null and {} (mismatched types null and struct):
93+
// ./in.cue:21:10
94+
// ./in.cue:22:5
95+
// eliminated.x.n: field not allowed:
96+
// ./in.cue:23:5
97+
// ./in.cue:23:16
98+
n: (_|_){
99+
// [eval] eliminated.x.n: field not allowed:
100+
// ./in.cue:23:5
101+
// ./in.cue:23:16
102+
}
103+
}
104+
out: (_|_){
105+
// [eval] eliminated.x: conflicting values null and {} (mismatched types null and struct):
106+
// ./in.cue:21:10
107+
// ./in.cue:22:5
108+
// eliminated.x.n: field not allowed:
109+
// ./in.cue:23:5
110+
// ./in.cue:23:16
111+
}
112+
}
113+
simplified: (_|_){
114+
// [eval]
115+
#struct: (#struct){
116+
field: (#struct){
117+
n: (int){ 3 }
118+
}
119+
g: (#struct){
120+
}
121+
}
122+
out: (_|_){
123+
// [eval]
124+
field: (_|_){
125+
// [eval]
126+
n: (_|_){
127+
// [eval] simplified.out.field.n: field not allowed:
128+
// ./in.cue:31:21
129+
// ./in.cue:31:12
130+
}
131+
}
132+
g: (#struct){
133+
}
134+
}
135+
}
136+
}
137+
-- diff/-out/evalalpha<==>+out/eval --
138+
diff old new
139+
--- old
140+
+++ new
141+
@@ -1,18 +1,25 @@
142+
Errors:
143+
-eliminated.x: 2 errors in empty disjunction:
144+
-eliminated.x: conflicting values null and {n:3} (mismatched types null and struct):
145+
+eliminated.x: conflicting values null and {} (mismatched types null and struct):
146+
+ ./in.cue:21:10
147+
./in.cue:22:5
148+
- ./in.cue:23:14
149+
+issue3330.0.0.field: conflicting values null and {} (mismatched types null and struct):
150+
+ ./in.cue:5:15
151+
+ ./in.cue:9:10
152+
+issue3330.0.0.field.n: field not allowed:
153+
+ ./in.cue:10:10
154+
+ ./in.cue:10:20
155+
eliminated.x.n: field not allowed:
156+
- ./in.cue:21:10
157+
- ./in.cue:22:14
158+
./in.cue:23:5
159+
./in.cue:23:16
160+
+simplified.out.field.n: field not allowed:
161+
+ ./in.cue:31:21
162+
+ ./in.cue:31:12
163+
164+
Result:
165+
(_|_){
166+
// [eval]
167+
- issue3330: (struct){
168+
+ issue3330: (_|_){
169+
+ // [eval]
170+
#A: (#struct){
171+
let empty#1 = (#struct){
172+
}
173+
@@ -20,14 +27,13 @@
174+
n: (int){ 3 }
175+
}
176+
}
177+
- out: (#list){
178+
- 0: (#struct){
179+
- let empty#1 = (#struct){
180+
- }
181+
- field: (#struct){
182+
- n: (int){ 3 }
183+
- }
184+
- }
185+
+ out: (_|_){
186+
+ // [eval] issue3330.0.0.field: conflicting values null and {} (mismatched types null and struct):
187+
+ // ./in.cue:5:15
188+
+ // ./in.cue:9:10
189+
+ // issue3330.0.0.field.n: field not allowed:
190+
+ // ./in.cue:10:10
191+
+ // ./in.cue:10:20
192+
}
193+
}
194+
eliminated: (_|_){
195+
@@ -35,36 +41,29 @@
196+
#empty: (#struct){
197+
}
198+
x: (_|_){
199+
- // [eval] eliminated.x: 2 errors in empty disjunction:
200+
- // eliminated.x: conflicting values null and {n:3} (mismatched types null and struct):
201+
- // ./in.cue:22:5
202+
- // ./in.cue:23:14
203+
- // eliminated.x.n: field not allowed:
204+
- // ./in.cue:21:10
205+
- // ./in.cue:22:14
206+
+ // [eval] eliminated.x: conflicting values null and {} (mismatched types null and struct):
207+
+ // ./in.cue:21:10
208+
+ // ./in.cue:22:5
209+
+ // eliminated.x.n: field not allowed:
210+
// ./in.cue:23:5
211+
// ./in.cue:23:16
212+
n: (_|_){
213+
// [eval] eliminated.x.n: field not allowed:
214+
- // ./in.cue:21:10
215+
- // ./in.cue:22:14
216+
// ./in.cue:23:5
217+
// ./in.cue:23:16
218+
}
219+
}
220+
out: (_|_){
221+
- // [eval] eliminated.x: 2 errors in empty disjunction:
222+
- // eliminated.x: conflicting values null and {n:3} (mismatched types null and struct):
223+
- // ./in.cue:22:5
224+
- // ./in.cue:23:14
225+
- // eliminated.x.n: field not allowed:
226+
- // ./in.cue:21:10
227+
- // ./in.cue:22:14
228+
- // ./in.cue:23:5
229+
- // ./in.cue:23:16
230+
- }
231+
- }
232+
- simplified: (struct){
233+
+ // [eval] eliminated.x: conflicting values null and {} (mismatched types null and struct):
234+
+ // ./in.cue:21:10
235+
+ // ./in.cue:22:5
236+
+ // eliminated.x.n: field not allowed:
237+
+ // ./in.cue:23:5
238+
+ // ./in.cue:23:16
239+
+ }
240+
+ }
241+
+ simplified: (_|_){
242+
+ // [eval]
243+
#struct: (#struct){
244+
field: (#struct){
245+
n: (int){ 3 }
246+
@@ -72,9 +71,15 @@
247+
g: (#struct){
248+
}
249+
}
250+
- out: (#struct){
251+
- field: (#struct){
252+
- n: (int){ 3 }
253+
+ out: (_|_){
254+
+ // [eval]
255+
+ field: (_|_){
256+
+ // [eval]
257+
+ n: (_|_){
258+
+ // [eval] simplified.out.field.n: field not allowed:
259+
+ // ./in.cue:31:21
260+
+ // ./in.cue:31:12
261+
+ }
262+
}
263+
g: (#struct){
264+
}
265+
-- diff/todo/p1 --
266+
References of structs within a definition that are usually allowed are
267+
now triggered by refering to a definition outside of that definition.
268+
Both "issue3330" and "simplified" should not have any errors.
269+
-- out/eval --
270+
Errors:
271+
eliminated.x: 2 errors in empty disjunction:
272+
eliminated.x: conflicting values null and {n:3} (mismatched types null and struct):
273+
./in.cue:22:5
274+
./in.cue:23:14
275+
eliminated.x.n: field not allowed:
276+
./in.cue:21:10
277+
./in.cue:22:14
278+
./in.cue:23:5
279+
./in.cue:23:16
280+
281+
Result:
282+
(_|_){
283+
// [eval]
284+
issue3330: (struct){
285+
#A: (#struct){
286+
let empty#1 = (#struct){
287+
}
288+
field: (#struct){
289+
n: (int){ 3 }
290+
}
291+
}
292+
out: (#list){
293+
0: (#struct){
294+
let empty#1 = (#struct){
295+
}
296+
field: (#struct){
297+
n: (int){ 3 }
298+
}
299+
}
300+
}
301+
}
302+
eliminated: (_|_){
303+
// [eval]
304+
#empty: (#struct){
305+
}
306+
x: (_|_){
307+
// [eval] eliminated.x: 2 errors in empty disjunction:
308+
// eliminated.x: conflicting values null and {n:3} (mismatched types null and struct):
309+
// ./in.cue:22:5
310+
// ./in.cue:23:14
311+
// eliminated.x.n: field not allowed:
312+
// ./in.cue:21:10
313+
// ./in.cue:22:14
314+
// ./in.cue:23:5
315+
// ./in.cue:23:16
316+
n: (_|_){
317+
// [eval] eliminated.x.n: field not allowed:
318+
// ./in.cue:21:10
319+
// ./in.cue:22:14
320+
// ./in.cue:23:5
321+
// ./in.cue:23:16
322+
}
323+
}
324+
out: (_|_){
325+
// [eval] eliminated.x: 2 errors in empty disjunction:
326+
// eliminated.x: conflicting values null and {n:3} (mismatched types null and struct):
327+
// ./in.cue:22:5
328+
// ./in.cue:23:14
329+
// eliminated.x.n: field not allowed:
330+
// ./in.cue:21:10
331+
// ./in.cue:22:14
332+
// ./in.cue:23:5
333+
// ./in.cue:23:16
334+
}
335+
}
336+
simplified: (struct){
337+
#struct: (#struct){
338+
field: (#struct){
339+
n: (int){ 3 }
340+
}
341+
g: (#struct){
342+
}
343+
}
344+
out: (#struct){
345+
field: (#struct){
346+
n: (int){ 3 }
347+
}
348+
g: (#struct){
349+
}
350+
}
351+
}
352+
}
353+
-- out/compile --
354+
--- in.cue
355+
{
356+
issue3330: {
357+
#A: {
358+
let empty#1 = {}
359+
field: (null|{
360+
n: int
361+
})
362+
field: (〈0;let empty#1〉 & {
363+
n: 3
364+
})
365+
}
366+
out: 〈import;list〉.Concat([
367+
[
368+
〈2;#A〉,
369+
],
370+
])
371+
}
372+
eliminated: {
373+
#empty: {}
374+
x: (null|{
375+
n: 3
376+
})
377+
x: (〈0;#empty〉 & {
378+
n: 3
379+
})
380+
out: len(〈0;x〉)
381+
}
382+
simplified: {
383+
#struct: {
384+
field: ({
385+
n: 3
386+
} & 〈0;g〉)
387+
g: {}
388+
}
389+
out: (〈0;#struct〉 & {})
390+
}
391+
}

0 commit comments

Comments
 (0)