fix #20233 Float ranges in case statement in JS crash compiler (#20349)

This commit is contained in:
Bung 2022-09-14 23:16:34 +08:00 • committed by GitHub
commit 08faa04d78
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 62 additions and 18 deletions

View file

@ -871,15 +871,19 @@ proc genRaiseStmt(p: PProc, n: PNode) =
proc genCaseJS(p: PProc, n: PNode, r: var TCompRes) = proc genCaseJS(p: PProc, n: PNode, r: var TCompRes) =
var var
cond, stmt: TCompRes a, b, cond, stmt: TCompRes
totalRange = 0 totalRange = 0
genLineDir(p, n) genLineDir(p, n)
gen(p, n[0], cond) gen(p, n[0], cond)
let typeKind = skipTypes(n[0].typ, abstractVar).kind let typeKind = skipTypes(n[0].typ, abstractVar).kind
var transferRange = false
let anyString = typeKind in {tyString, tyCstring} let anyString = typeKind in {tyString, tyCstring}
if typeKind == tyString: case typeKind
of tyString:
useMagic(p, "toJSStr") useMagic(p, "toJSStr")
lineF(p, "switch (toJSStr($1)) {$n", [cond.rdLoc]) lineF(p, "switch (toJSStr($1)) {$n", [cond.rdLoc])
of tyFloat..tyFloat128:
transferRange = true
else: else:
lineF(p, "switch ($1) {$n", [cond.rdLoc]) lineF(p, "switch ($1) {$n", [cond.rdLoc])
if not isEmptyType(n.typ): if not isEmptyType(n.typ):
@ -887,11 +891,25 @@ proc genCaseJS(p: PProc, n: PNode, r: var TCompRes) =
r.res = getTemp(p) r.res = getTemp(p)
for i in 1..<n.len: for i in 1..<n.len:
let it = n[i] let it = n[i]
let itLen = it.len
case it.kind case it.kind
of nkOfBranch: of nkOfBranch:
for j in 0..<it.len - 1: if transferRange:
if i == 1:
lineF(p, "if (", [])
else:
lineF(p, "else if (", [])
for j in 0..<itLen - 1:
let e = it[j] let e = it[j]
if e.kind == nkRange: if e.kind == nkRange:
if transferRange:
gen(p, e[0], a)
gen(p, e[1], b)
if j != itLen - 2:
lineF(p, "$1 >= $2 && $1 <= $3 || $n", [cond.rdLoc, a.rdLoc, b.rdLoc])
else:
lineF(p, "$1 >= $2 && $1 <= $3", [cond.rdLoc, a.rdLoc, b.rdLoc])
else:
var v = copyNode(e[0]) var v = copyNode(e[0])
inc(totalRange, int(e[1].intVal - v.intVal)) inc(totalRange, int(e[1].intVal - v.intVal))
if totalRange > 65535: if totalRange > 65535:
@ -909,19 +927,38 @@ proc genCaseJS(p: PProc, n: PNode, r: var TCompRes) =
of nkNilLit: lineF(p, "case null:$n", []) of nkNilLit: lineF(p, "case null:$n", [])
else: internalError(p.config, e.info, "jsgen.genCaseStmt: 2") else: internalError(p.config, e.info, "jsgen.genCaseStmt: 2")
else: else:
gen(p, e, cond) if transferRange:
lineF(p, "case $1:$n", [cond.rdLoc]) gen(p, e, a)
if j != itLen - 2:
lineF(p, "$1 == $2 || $n", [cond.rdLoc, a.rdLoc])
else:
lineF(p, "$1 == $2", [cond.rdLoc, a.rdLoc])
else:
gen(p, e, a)
lineF(p, "case $1:$n", [a.rdLoc])
if transferRange:
lineF(p, "){", [])
p.nested: p.nested:
gen(p, lastSon(it), stmt) gen(p, lastSon(it), stmt)
moveInto(p, stmt, r) moveInto(p, stmt, r)
if transferRange:
lineF(p, "}$n", [])
else:
lineF(p, "break;$n", []) lineF(p, "break;$n", [])
of nkElse: of nkElse:
if transferRange:
lineF(p, "else{$n", [])
else:
lineF(p, "default: $n", []) lineF(p, "default: $n", [])
p.nested: p.nested:
gen(p, it[0], stmt) gen(p, it[0], stmt)
moveInto(p, stmt, r) moveInto(p, stmt, r)
if transferRange:
lineF(p, "}$n", [])
else:
lineF(p, "break;$n", []) lineF(p, "break;$n", [])
else: internalError(p.config, it.info, "jsgen.genCaseStmt") else: internalError(p.config, it.info, "jsgen.genCaseStmt")
if not transferRange:
lineF(p, "}$n", []) lineF(p, "}$n", [])
proc genBlock(p: PProc, n: PNode, r: var TCompRes) = proc genBlock(p: PProc, n: PNode, r: var TCompRes) =

7
tests/js/t20233.nim Normal file
View file

@ -0,0 +1,7 @@
discard """
output: "yes"
"""
case 1.0
of 1.0..2.0, 4.0: echo "yes"
of 3.0: discard
else: echo "no"