Skip to content

Commit de73c26

Browse files
authored
Make sure reachable_var not falls into infinite recusion. (#48135)
1 parent 8dbf7a1 commit de73c26

File tree

2 files changed

+43
-3
lines changed

2 files changed

+43
-3
lines changed

src/subtype.c

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,17 @@ static void restore_env(jl_stenv_t *e, jl_value_t *root, jl_savedenv_t *se) JL_N
216216
memset(&e->envout[e->envidx], 0, (e->envsz - e->envidx)*sizeof(void*));
217217
}
218218

219+
static int current_env_length(jl_stenv_t *e)
220+
{
221+
jl_varbinding_t *v = e->vars;
222+
int len = 0;
223+
while (v) {
224+
len++;
225+
v = v->prev;
226+
}
227+
return len;
228+
}
229+
219230
// type utilities
220231

221232
// quickly test that two types are identical
@@ -2302,16 +2313,40 @@ static int subtype_in_env_existential(jl_value_t *x, jl_value_t *y, jl_stenv_t *
23022313
}
23032314

23042315
// See if var y is reachable from x via bounds; used to avoid cycles.
2305-
static int reachable_var(jl_value_t *x, jl_tvar_t *y, jl_stenv_t *e)
2316+
static int _reachable_var(jl_value_t *x, jl_tvar_t *y, jl_stenv_t *e)
23062317
{
23072318
if (in_union(x, (jl_value_t*)y))
23082319
return 1;
23092320
if (!jl_is_typevar(x))
23102321
return 0;
23112322
jl_varbinding_t *xv = lookup(e, (jl_tvar_t*)x);
2312-
if (xv == NULL)
2323+
if (xv == NULL || xv->right)
23132324
return 0;
2314-
return reachable_var(xv->ub, y, e) || reachable_var(xv->lb, y, e);
2325+
xv->right = 1;
2326+
return _reachable_var(xv->ub, y, e) || _reachable_var(xv->lb, y, e);
2327+
}
2328+
2329+
static int reachable_var(jl_value_t *x, jl_tvar_t *y, jl_stenv_t *e)
2330+
{
2331+
int len = current_env_length(e);
2332+
int8_t *rs = (int8_t*)malloc_s(len);
2333+
int n = 0;
2334+
jl_varbinding_t *v = e->vars;
2335+
while (n < len) {
2336+
assert(v != NULL);
2337+
rs[n++] = v->right;
2338+
v->right = 0;
2339+
v = v->prev;
2340+
}
2341+
int res = _reachable_var(x, y, e);
2342+
n = 0; v = e->vars;
2343+
while (n < len) {
2344+
assert(v != NULL);
2345+
v->right = rs[n++];
2346+
v = v->prev;
2347+
}
2348+
free(rs);
2349+
return res;
23152350
}
23162351

23172352
// check whether setting v == t implies v == SomeType{v}, which is unsatisfiable.

test/subtype.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2314,6 +2314,11 @@ let S1 = Tuple{Int, Any, Union{Val{C1}, C1}} where {R1<:Real, C1<:Union{Complex{
23142314
end
23152315
end
23162316

2317+
let S = Tuple{T2, V2} where {T2, N2, V2<:(Array{S2, N2} where {S2 <: T2})},
2318+
T = Tuple{V1, T1} where {T1, N1, V1<:(Array{S1, N1} where {S1 <: T1})}
2319+
@testintersect(S, T, !Union{})
2320+
end
2321+
23172322
@testset "known subtype/intersect issue" begin
23182323
#issue 45874
23192324
# Causes a hang due to jl_critical_error calling back into malloc...

0 commit comments

Comments
 (0)