Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Floating point exception in builtin.c #1176

Closed
moraxy opened this issue Jul 2, 2016 · 3 comments · Fixed by #2629
Closed

Floating point exception in builtin.c #1176

moraxy opened this issue Jul 2, 2016 · 3 comments · Fixed by #2629
Labels
Milestone

Comments

@moraxy
Copy link

moraxy commented Jul 2, 2016

Tested against the current master and jqplay.org

$ ./jq -n 'infinite%-1'                                                                                
Floating point exception

gdb

Program received signal SIGFPE, Arithmetic exception.
0x0000000000493836 in f_mod (jq=<optimized out>, input=..., a=..., b=...) at src/builtin.c:263
263         return jv_number((intmax_t)jv_number_value(a) % (intmax_t)jv_number_value(b));
(gdb) bt
#0  0x0000000000493836 in f_mod (jq=<optimized out>, input=..., a=..., b=...) at src/builtin.c:263
#1  0x0000000000415510 in jq_next (jq=jq@entry=0x716150) at src/execute.c:786
#2  0x00000000004077e8 in process (jq=0x716150, value=..., flags=flags@entry=0, dumpopts=dumpopts@entry=645) at src/main.c:151
#3  0x0000000000406607 in main (argc=<optimized out>, argv=<optimized out>) at src/main.c:546
(gdb) l
 258     static jv f_mod(jq_state *jq, jv input, jv a, jv b) {
 259       jv_free(input);
 260       if (jv_get_kind(a) == JV_KIND_NUMBER && jv_get_kind(b) == JV_KIND_NUMBER) {
 261         if ((intmax_t)jv_number_value(b) == 0)
 262           return type_error2(a, b, "cannot be divided (remainder) because the divisor is zero");
>263         return jv_number((intmax_t)jv_number_value(a) % (intmax_t)jv_number_value(b));
 264       } else {
 265         return type_error2(a, b, "cannot be divided (remainder)");
 266       }
 267     }

Possibly related to #750 ?

@pallas
Copy link
Contributor

pallas commented Mar 25, 2019

I just ran into this too. The issue is that due to the size of the dividend and the fact that the negative divisor inverts the sign, the result can not be represented in intmax_t.

@nicowilliams
Copy link
Contributor

nicowilliams commented Mar 25, 2019

Yeah, so we need to disable generation of SIGFPE, with fedisableexcept(FE_ALL_EXCEPT). If not available, I guess we can always ignore SIGFPE.

@nicowilliams
Copy link
Contributor

Something like the following hack fixes this particular crash, but the sin here is to have defined the % remainder operator in terms of the C integer remainder operator rather than using fmod() from libm, so it might be better to actually re-implement the f_mod() function:

diff --git a/src/builtin.c b/src/builtin.c
index 01528b6..ca1ba72 100644
--- a/src/builtin.c
+++ b/src/builtin.c
@@ -349,6 +349,9 @@ static jv f_mod(jq_state *jq, jv input, jv a, jv b) {
   if (jv_get_kind(a) == JV_KIND_NUMBER && jv_get_kind(b) == JV_KIND_NUMBER) {
     if ((intmax_t)jv_number_value(b) == 0)
       return type_error2(a, b, "cannot be divided (remainder) because the divisor is zero");
+    double x = fmod(jv_number_value(a), jv_number_value(b));
+    if (isnan(x))
+      return type_error2(a, b, "integer overflow computing remainder");
     return jv_number((intmax_t)jv_number_value(a) % (intmax_t)jv_number_value(b));
   } else {
     return type_error2(a, b, "cannot be divided (remainder)");

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants