mirror of
https://github.com/golang/go
synced 2024-09-06 00:19:45 +00:00
cmd/gc: check exponent overflow and underflow in mparith
A too large float constant is an error. A too small float constant is rounded to zero. Fixes #7419 Update #6902 LGTM=iant R=golang-codereviews, iant CC=golang-codereviews https://golang.org/cl/76730046
This commit is contained in:
parent
50f1e1a6b9
commit
cb50277510
|
@ -1255,6 +1255,7 @@ void mpmovecflt(Mpflt *a, double c);
|
|||
void mpmulfltflt(Mpflt *a, Mpflt *b);
|
||||
void mpnegflt(Mpflt *a);
|
||||
void mpnorm(Mpflt *a);
|
||||
void mpsetexp(Mpflt *a, int exp);
|
||||
int mptestflt(Mpflt *a);
|
||||
int sigfig(Mpflt *a);
|
||||
|
||||
|
|
|
@ -416,7 +416,7 @@ mpatoflt(Mpflt *a, char *as)
|
|||
if(eb) {
|
||||
if(dp)
|
||||
goto bad;
|
||||
a->exp += ex;
|
||||
mpsetexp(a, a->exp+ex);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -427,10 +427,15 @@ mpatoflt(Mpflt *a, char *as)
|
|||
mppow10flt(&b, ex-dp);
|
||||
mpmulfltflt(a, &b);
|
||||
} else {
|
||||
if((short)(dp-ex) != dp-ex) {
|
||||
mpmovecflt(a, 0.0);
|
||||
}
|
||||
else {
|
||||
mppow10flt(&b, dp-ex);
|
||||
mpdivfltflt(a, &b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if(f)
|
||||
|
|
|
@ -22,6 +22,27 @@ sigfig(Mpflt *a)
|
|||
return i+1;
|
||||
}
|
||||
|
||||
/*
|
||||
* sets the exponent.
|
||||
* a too large exponent is an error.
|
||||
* a too small exponent rounds the number to zero.
|
||||
*/
|
||||
void
|
||||
mpsetexp(Mpflt *a, int exp) {
|
||||
if((short)exp != exp) {
|
||||
if(exp > 0) {
|
||||
yyerror("float constant is too large");
|
||||
a->exp = 0x7fff;
|
||||
}
|
||||
else {
|
||||
mpmovecflt(a, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
a->exp = exp;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* shifts the leading non-zero
|
||||
* word of the number to Mpnorm
|
||||
|
@ -60,7 +81,7 @@ mpnorm(Mpflt *a)
|
|||
}
|
||||
|
||||
mpshiftfix(&a->val, s);
|
||||
a->exp -= s;
|
||||
mpsetexp(a, a->exp-s);
|
||||
}
|
||||
|
||||
/// implements float arihmetic
|
||||
|
@ -95,7 +116,7 @@ mpaddfltflt(Mpflt *a, Mpflt *b)
|
|||
if(s < 0) {
|
||||
// b is larger, shift a right
|
||||
mpshiftfix(&a->val, s);
|
||||
a->exp -= s;
|
||||
mpsetexp(a, a->exp-s);
|
||||
mpaddfixfix(&a->val, &b->val, 0);
|
||||
goto out;
|
||||
}
|
||||
|
@ -131,7 +152,7 @@ mpmulfltflt(Mpflt *a, Mpflt *b)
|
|||
}
|
||||
|
||||
mpmulfract(&a->val, &b->val);
|
||||
a->exp = (a->exp + b->exp) + Mpscale*Mpprec - Mpscale - 1;
|
||||
mpsetexp(a, (a->exp + b->exp) + Mpscale*Mpprec - Mpscale - 1);
|
||||
|
||||
mpnorm(a);
|
||||
if(Mpdebug)
|
||||
|
@ -171,7 +192,7 @@ mpdivfltflt(Mpflt *a, Mpflt *b)
|
|||
|
||||
// divide
|
||||
mpdivfract(&a->val, &c.val);
|
||||
a->exp = (a->exp-c.exp) - Mpscale*(Mpprec-1) + 1;
|
||||
mpsetexp(a, (a->exp-c.exp) - Mpscale*(Mpprec-1) + 1);
|
||||
|
||||
mpnorm(a);
|
||||
if(Mpdebug)
|
||||
|
@ -199,7 +220,10 @@ mpgetflt(Mpflt *a)
|
|||
|
||||
while((a->val.a[Mpnorm-1] & Mpsign) == 0) {
|
||||
mpshiftfix(&a->val, 1);
|
||||
a->exp -= 1;
|
||||
mpsetexp(a, a->exp-1); // can set 'a' to zero
|
||||
s = sigfig(a);
|
||||
if(s == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// the magic numbers (64, 63, 53, 10, -1074) are
|
||||
|
|
25
test/fixedbugs/issue7419.go
Normal file
25
test/fixedbugs/issue7419.go
Normal file
|
@ -0,0 +1,25 @@
|
|||
// run
|
||||
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Issue 7419: odd behavior for float constants underflowing to 0
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
var x = 1e-779137
|
||||
var y = 1e-779138
|
||||
|
||||
func main() {
|
||||
if x != 0 {
|
||||
os.Exit(1)
|
||||
}
|
||||
if y != 0 {
|
||||
os.Exit(2)
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue