Prevent compiler stack overflow on long acyclic forward type-alias chains

Abierto
#1,068 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

@hiyouwhatsapp ya está trabajando en esto.

Desde el 2/11/2026.

  • #1074 de @hiyouwhatsapp — abierto

Evaluación

Dificultad
4/5
Tiempo estimado
3-5 días
Aptitud para principiantes
35/100
Tipo de issue
Error
Claridad
Bastante claro
Estado de actividad
Activo
Stack tecnológico
rust
Área
compilers

Línea de trabajo

Start with the type canonicalization code in front/parser/src/verification/program.rs and the alias graph validation paths it reaches. Run the Python reproduction from the issue against target/debug/wavec to get the SIGABRT, then find which recursive function first exhausts the stack. Done means the 16384-alias chain completes or returns a normal diagnostic, direct and indirect alias cycles still get rejected, and tests cover forward and backward declaration order.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

bug

Problem

A long acyclic chain of forward type aliases aborts wavec check with a stack overflow instead of completing or returning a normal source diagnostic. Each declaration contains only a shallow named type, so the syntactic type-depth guard does not bound semantic traversal through the alias graph.

This is a Wave compiler robustness defect. It is not evidence of a Rust standard-library or compiler vulnerability.

Starting points: type canonicalization and the alias graph validation paths. The end-to-end abort is confirmed; the exact recursive function that first exhausts the stack has not been isolated.

Reproduction

Tested on Linux amd64 with a checkout-built wavec 0.0.1-alpha-dev, Rust 1.89.0 and LLVM 21. Local revision f7ff92c54bf8b41c2877245788890935b4ca3ba1; the frontend and driver source are identical to canonical master 1d1751405e087f32c1b1f28399d1629ae1bcfbd2 for this reproduction.

Run from the checkout. This creates only a temporary source, disables core dumps in the child and bounds the compiler invocation:

from pathlib import Path
import resource
import subprocess
import tempfile

compiler = str(Path('target/debug/wavec').resolve())

def limits():
    resource.setrlimit(resource.RLIMIT_CORE, (0, 0))

with tempfile.TemporaryDirectory() as temporary:
    source = Path(temporary) / 'aliases.wave'
    count = 16384
    source.write_text(
        '\n'.join(f'type A{i} = A{i + 1};' for i in range(count - 1))
        + f'\ntype A{count - 1} = i32;\n'
        + 'fun main() { var x: A0 = 0; }\n',
        encoding='utf-8',
    )
    result = subprocess.run(
        [compiler, 'check', str(source), '--error-format=json'],
        capture_output=True, text=True, timeout=12, preexec_fn=limits,
    )
    print(result.returncode)
    print(result.stderr)

Observed exit -6 (SIGABRT):

thread 'main' has overflowed its stack
fatal runtime error: stack overflow, aborting

The host-dependent failure threshold is not a proposed language limit. Separate 4096- and 8192-alias probes exceeded the 12-second observation window; that does not establish an asymptotic complexity claim.

Scope

Make semantic alias traversal safe for long acyclic graphs while preserving supported forward aliases and existing recursive-alias rejection. Preserve normal structured and JSON diagnostics. Do not increase the OS stack size or silently replace unresolved types.

Related: #167 rejects cycles; #852 bounds syntactic block/type nesting; #1029 bounds import depth. None covers this shallow, acyclic alias graph.

Completion criteria

  • A long acyclic forward alias chain no longer aborts the compiler.
  • Direct and indirect cycles still receive normal diagnostics.
  • Tests cover forward/backward declaration order and aliases used by ordinary type checking and code generation.
  • Any newly proposed rejection limit is discussed before changing accepted-language semantics.
Lenguaje dominante
Rust
Estrellas
56
Forks
21
Merge medio
20 h 49 min
PR fusionados (30 d)
45

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de wavefnd/Wave

Todos los issues de wavefnd/Wave

Issues similares

Más issues de Rust

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.