-
Notifications
You must be signed in to change notification settings - Fork 1k
Closes #5510: undefined behaviour #5832
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
Changes from all commits
0471c4d
e3c6a78
90b167e
47c87fd
772906d
c1bf61c
2d76efd
f0238b4
7696ea3
61ce9dd
e9f9ba1
e00a553
9d05feb
a27ccf2
50056ef
cd73555
d32470e
46cf79c
3e2f1c3
7701738
b269b39
6f2769f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,9 @@ | ||
| { | ||
| "build": { "dockerfile": "Dockerfile", "context": "../.." }, | ||
| "customizations": { "vscode": { "extensions": [ "REditorSupport.r" ] } } | ||
| "customizations": { "vscode": { | ||
| "extensions": [ | ||
| "REditorSupport.r", | ||
| "ms-vscode.cpptools-extension-pack" | ||
| ] | ||
| }} | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,9 @@ | ||
| { | ||
| "build": { "dockerfile": "Dockerfile", "context": "../.." }, | ||
| "customizations": { "vscode": { "extensions": [ "REditorSupport.r" ] } } | ||
| "customizations": { "vscode": { | ||
| "extensions": [ | ||
| "REditorSupport.r", | ||
| "ms-vscode.cpptools-extension-pack" | ||
| ] | ||
| }} | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -239,7 +239,7 @@ int checkOverAlloc(SEXP x) | |
| error(_("getOption('datatable.alloccol') should be a number, by default 1024. But its type is '%s'."), type2char(TYPEOF(x))); | ||
| if (LENGTH(x) != 1) | ||
| error(_("getOption('datatable.alloc') is a numeric vector ok but its length is %d. Its length should be 1."), LENGTH(x)); | ||
| int ans = isInteger(x) ? INTEGER(x)[0] : (int)REAL(x)[0]; | ||
| int ans = asInteger(x); | ||
| if (ans<0) | ||
| error(_("getOption('datatable.alloc')==%d. It must be >=0 and not NA."), ans); | ||
| return ans; | ||
|
|
@@ -742,7 +742,8 @@ const char *memrecycle(const SEXP target, const SEXP where, const int start, con | |
| const double *sd = REAL(source); | ||
| for (int i=0; i<slen; ++i) { | ||
| const double val = sd[i+soff]; | ||
| if (!ISNAN(val) && (!R_FINITE(val) || val!=(int)val || (int)val<1 || (int)val>nlevel)) { | ||
| // Since nlevel is an int, val < 1 || val > nlevel will deflect UB guarded against in PR #5832 | ||
| if (!ISNAN(val) && (val < 1 || val > nlevel || val != (int)val)) { | ||
| error(_("Assigning factor numbers to %s. But %f is outside the level range [1,%d], or is not a whole number."), targetDesc(colnum, colname), val, nlevel); | ||
| } | ||
| } | ||
|
|
@@ -897,14 +898,14 @@ const char *memrecycle(const SEXP target, const SEXP where, const int start, con | |
| switch (TYPEOF(source)) { | ||
| case REALSXP: if (sourceIsI64) | ||
| CHECK_RANGE(int64_t, REAL, val!=NA_INTEGER64 && (val<=NA_INTEGER || val>INT_MAX), PRId64, "out-of-range (NA)", val) | ||
HughParsonage marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| else CHECK_RANGE(double, REAL, !ISNAN(val) && (!R_FINITE(val) || (int)val!=val), "f", "truncated (precision lost)", val) | ||
| else CHECK_RANGE(double, REAL, !ISNAN(val) && (!within_int32_repres(val) || (int)val!=val), "f", "out-of-range(NA) or truncated (precision lost)", val) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see |
||
| case CPLXSXP: CHECK_RANGE(Rcomplex, COMPLEX, !((ISNAN(val.i) || (R_FINITE(val.i) && val.i==0.0)) && | ||
| (ISNAN(val.r) || (R_FINITE(val.r) && (int)val.r==val.r))), "f", "either imaginary part discarded or real part truncated (precision lost)", val.r) | ||
| (ISNAN(val.r) || (within_int32_repres(val.r) && (int)val.r==val.r))), "f", "either imaginary part discarded or real part truncated (precision lost)", val.r) | ||
| } break; | ||
| case REALSXP: | ||
| switch (TYPEOF(source)) { | ||
| case REALSXP: if (targetIsI64 && !sourceIsI64) | ||
| CHECK_RANGE(double, REAL, !ISNAN(val) && (!R_FINITE(val) || (int64_t)val!=val), "f", "truncated (precision lost)", val) | ||
| CHECK_RANGE(double, REAL, !ISNAN(val) && (!within_int64_repres(val) || (int64_t)val!=val), "f", "out-of-range(NA) or truncated (precision lost)", val) | ||
| break; | ||
| case CPLXSXP: if (targetIsI64) | ||
| CHECK_RANGE(Rcomplex, COMPLEX, !((ISNAN(val.i) || (R_FINITE(val.i) && val.i==0.0)) && | ||
|
|
@@ -1004,8 +1005,8 @@ const char *memrecycle(const SEXP target, const SEXP where, const int start, con | |
| case REALSXP: | ||
| if (sourceIsI64) | ||
| BODY(int64_t, REAL, int, (val==NA_INTEGER64||val>INT_MAX||val<=NA_INTEGER) ? NA_INTEGER : (int)val, td[i]=cval) | ||
HughParsonage marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| else BODY(double, REAL, int, ISNAN(val) ? NA_INTEGER : (int)val, td[i]=cval) | ||
| case CPLXSXP: BODY(Rcomplex, COMPLEX, int, ISNAN(val.r) ? NA_INTEGER : (int)val.r, td[i]=cval) | ||
| else BODY(double, REAL, int, (ISNAN(val) || !within_int32_repres(val)) ? NA_INTEGER : (int)val, td[i]=cval) | ||
| case CPLXSXP: BODY(Rcomplex, COMPLEX, int, (ISNAN(val.r) || !within_int32_repres(val.r)) ? NA_INTEGER : (int)val.r, td[i]=cval) | ||
| default: COERCE_ERROR("integer"); // test 2005.4 | ||
| } | ||
| } break; | ||
|
|
@@ -1021,7 +1022,7 @@ const char *memrecycle(const SEXP target, const SEXP where, const int start, con | |
| if (mc) { | ||
| memcpy(td, (int64_t *)REAL(source), slen*sizeof(int64_t)); break; | ||
| } else BODY(int64_t, REAL, int64_t, val, td[i]=cval) | ||
| } else BODY(double, REAL, int64_t, R_FINITE(val) ? val : NA_INTEGER64, td[i]=cval) | ||
| } else BODY(double, REAL, int64_t, within_int64_repres(val) ? val : NA_INTEGER64, td[i]=cval) | ||
| case CPLXSXP: BODY(Rcomplex, COMPLEX, int64_t, ISNAN(val.r) ? NA_INTEGER64 : (int64_t)val.r, td[i]=cval) | ||
| default: COERCE_ERROR("integer64"); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,11 +1,22 @@ | ||
| #include "data.table.h" | ||
|
|
||
| bool within_int32_repres(double x) { | ||
| // N.B. (int)2147483647.99 is not undefined behaviour since s 6.3.1.4 of the C | ||
HughParsonage marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| // standard states that behaviour is undefined only if the integral part of a | ||
| // finite value of standard floating type cannot be represented. | ||
| return R_FINITE(x) && x < 2147483648 && x > -2147483648; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remind me, If it's redundant, remove it, otherwise, make sure we have a regression test in place for that edge case.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. actually not sure if warning is expected, we need to check if some tests are failing if we add this warning now. this function is meant to be use internally as well, and then raising warnings may be less desired.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As far as I can see, the only circumstance this comes up is for the peculiar: nafill(NA_integer_, fill = -2^31)That is, setting fill to the double value that is the same as |
||
| } | ||
|
|
||
| bool within_int64_repres(double x) { | ||
| return R_FINITE(x) && x <= (double)INT64_MAX && x >= (double)INT64_MIN; | ||
| } | ||
|
|
||
| static R_xlen_t firstNonInt(SEXP x) { | ||
| R_xlen_t n=xlength(x), i=0; | ||
| const double *dx = REAL(x); | ||
| while (i<n && | ||
| ( ISNA(dx[i]) || | ||
| ( R_FINITE(dx[i]) && dx[i]==(int)(dx[i]) && (int)(dx[i])!=NA_INTEGER))) { // NA_INTEGER == INT_MIN == -2147483648 | ||
| (within_int32_repres(dx[i]) && dx[i]==(int)(dx[i])))) { | ||
| i++; | ||
| } | ||
| return i==n ? 0 : i+1; | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.