-
Notifications
You must be signed in to change notification settings - Fork 560
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
[WASM] Integer Overflow on 'size' after stat'ing #22924
Comments
I "fixed" this by patching diff --git a/pp_sys.c b/pp_sys.c
index 5f8bb0d6ed..975e3a3877 100644
--- a/pp_sys.c
+++ b/pp_sys.c
@@ -2271,7 +2271,7 @@ PP_wrapped(pp_syswrite, 0, 1)
if (MARK >= SP) {
length = blen;
} else {
-#if Size_t_size > IVSIZE
+#if Size_t_size > IVSIZE || defined(__wasi__)
length = (Size_t)SvNVx(*++MARK);
#else
length = (Size_t)SvIVx(*++MARK);
@@ -2313,7 +2313,7 @@ PP_wrapped(pp_syswrite, 0, 1)
goto say_undef;
SP = ORIGMARK;
-#if Size_t_size > IVSIZE
+#if Size_t_size > IVSIZE || defined(__wasi__)
PUSHn(retval);
#else
PUSHi(retval);
@@ -2418,7 +2418,7 @@ PP_wrapped(pp_tell, MAXARG, 0)
RETURN;
}
-#if LSEEKSIZE > IVSIZE
+#if LSEEKSIZE > IVSIZE || defined(__wasi__)
PUSHn( (NV)do_tell(gv) );
#else
PUSHi( (IV)do_tell(gv) );
@@ -2433,7 +2433,7 @@ PP_wrapped(pp_sysseek, 3, 0)
{
dSP;
const int whence = POPi;
-#if LSEEKSIZE > IVSIZE
+#if LSEEKSIZE > IVSIZE || defined(__wasi__)
const Off_t offset = (Off_t)SvNVx(POPs);
#else
const Off_t offset = (Off_t)SvIVx(POPs);
@@ -2445,7 +2445,7 @@ PP_wrapped(pp_sysseek, 3, 0)
if (io) {
const MAGIC * const mg = SvTIED_mg((const SV *)io, PERL_MAGIC_tiedscalar);
if (mg) {
-#if LSEEKSIZE > IVSIZE
+#if LSEEKSIZE > IVSIZE || defined(__wasi__)
SV *const offset_sv = newSVnv((NV) offset);
#else
SV *const offset_sv = newSViv(offset);
@@ -2464,7 +2464,7 @@ PP_wrapped(pp_sysseek, 3, 0)
PUSHs(&PL_sv_undef);
else {
SV* const sv = sought ?
-#if LSEEKSIZE > IVSIZE
+#if LSEEKSIZE > IVSIZE || defined(__wasi__)
newSVnv((NV)sought)
#else
newSViv(sought)
@@ -2486,7 +2486,7 @@ PP_wrapped(pp_truncate, 2, 0)
/* XXX Configure probe for the length type of *truncate() needed XXX */
Off_t len;
-#if Off_t_size > IVSIZE
+#if Off_t_size > IVSIZE || defined(__wasi__)
len = (Off_t)POPn;
#else
len = (Off_t)POPi;
@@ -3267,7 +3267,7 @@ PP_wrapped(pp_stat, !(PL_op->op_flags & OPf_REF), 0)
#else
PUSHs(newSVpvs_flags("", SVs_TEMP));
#endif
-#if Off_t_size > IVSIZE
+#if Off_t_size > IVSIZE || defined(__wasi__)
mPUSHn(PL_statcache.st_size);
#else
mPUSHi(PL_statcache.st_size);
@@ -3524,7 +3524,7 @@ PP(pp_ftis)
dTARGET;
switch (op_type) {
case OP_FTSIZE:
-#if Off_t_size > IVSIZE
+#if Off_t_size > IVSIZE || defined(__wasi__)
sv_setnv(TARG, (NV)PL_statcache.st_size);
#else
sv_setiv(TARG, (IV)PL_statcache.st_size); |
So either #define VALUE_TO_STRING(x) #x
#define VALUE(x) VALUE_TO_STRING(x)
#define VAR_NAME_VALUE(var) #var "=" VALUE(var)
#pragma message(VAR_NAME_VALUE(Size_t_size))
#pragma message(VAR_NAME_VALUE(LSEEKSIZE))
#pragma message(VAR_NAME_VALUE(Off_t_size))
#pragma message(VAR_NAME_VALUE(IVSIZE)) Or maybe it determines these correctly and |
That is exactly what I wanted to recommend you when I had only read the title, so that is weird indeed. What is the value of Also, I'm not sure you should set |
I tried with
It's entirely possible in the rapid testing of builds I ended up supplying values that conflict with each other. I added some additional logging and this is what is reported when I call === File Size Configuration === For |
Just a wild guess, but what happens if you change that |
That also worked, though I applied the same idea to diff --git a/pp_sys.c b/pp_sys.c
index 5f8bb0d6ed..6dfb479e04 100644
--- a/pp_sys.c
+++ b/pp_sys.c
@@ -2274,7 +2274,7 @@ PP_wrapped(pp_syswrite, 0, 1)
#if Size_t_size > IVSIZE
length = (Size_t)SvNVx(*++MARK);
#else
- length = (Size_t)SvIVx(*++MARK);
+ length = (Size_t)SvUVx(*++MARK);
#endif
if ((SSize_t)length < 0) {
DIE(aTHX_ "Negative length");
@@ -2316,7 +2316,7 @@ PP_wrapped(pp_syswrite, 0, 1)
#if Size_t_size > IVSIZE
PUSHn(retval);
#else
- PUSHi(retval);
+ PUSHu(retval);
#endif
RETURN;
@@ -2421,7 +2421,7 @@ PP_wrapped(pp_tell, MAXARG, 0)
#if LSEEKSIZE > IVSIZE
PUSHn( (NV)do_tell(gv) );
#else
- PUSHi( (IV)do_tell(gv) );
+ PUSHu( (UV)do_tell(gv) );
#endif
RETURN;
}
@@ -2436,7 +2436,7 @@ PP_wrapped(pp_sysseek, 3, 0)
#if LSEEKSIZE > IVSIZE
const Off_t offset = (Off_t)SvNVx(POPs);
#else
- const Off_t offset = (Off_t)SvIVx(POPs);
+ const Off_t offset = (Off_t)SvUVx(POPs);
#endif
GV * const gv = PL_last_in_gv = MUTABLE_GV(POPs);
@@ -2448,7 +2448,7 @@ PP_wrapped(pp_sysseek, 3, 0)
#if LSEEKSIZE > IVSIZE
SV *const offset_sv = newSVnv((NV) offset);
#else
- SV *const offset_sv = newSViv(offset);
+ SV *const offset_sv = newSVuv(offset);
#endif
return tied_method2(SV_CONST(SEEK), SP, MUTABLE_SV(io), mg, offset_sv,
@@ -2467,7 +2467,7 @@ PP_wrapped(pp_sysseek, 3, 0)
#if LSEEKSIZE > IVSIZE
newSVnv((NV)sought)
#else
- newSViv(sought)
+ newSVuv(sought)
#endif
: newSVpvn(zero_but_true, ZBTLEN);
mPUSHs(sv);
@@ -2489,7 +2489,7 @@ PP_wrapped(pp_truncate, 2, 0)
#if Off_t_size > IVSIZE
len = (Off_t)POPn;
#else
- len = (Off_t)POPi;
+ len = (Off_t)POPu;
#endif
/* Checking for length < 0 is problematic as the type might or
* might not be signed: if it is not, clever compilers will moan. */
@@ -3270,7 +3270,7 @@ PP_wrapped(pp_stat, !(PL_op->op_flags & OPf_REF), 0)
#if Off_t_size > IVSIZE
mPUSHn(PL_statcache.st_size);
#else
- mPUSHi(PL_statcache.st_size);
+ mPUSHu(PL_statcache.st_size);
#endif
#ifdef BIG_TIME
mPUSHn(PL_statcache.st_atime);
@@ -3527,7 +3527,7 @@ PP(pp_ftis)
#if Off_t_size > IVSIZE
sv_setnv(TARG, (NV)PL_statcache.st_size);
#else
- sv_setiv(TARG, (IV)PL_statcache.st_size);
+ sv_setiv(TARG, (UV)PL_statcache.st_size);
#endif
break;
case OP_FTMTIME: I might have done something incorrect though, so I can look with fresh eyes later. |
This may be this issue. That said, that doesn't explain the the 32-bit part of the issue. My best guess is that it's because of |
The return values of |
Thanks @Leont. I removed diff --git a/pp_sys.c b/pp_sys.c
index 5f8bb0d6ed..ad8e46e692 100644
--- a/pp_sys.c
+++ b/pp_sys.c
@@ -3270,7 +3270,7 @@ PP_wrapped(pp_stat, !(PL_op->op_flags & OPf_REF), 0)
#if Off_t_size > IVSIZE
mPUSHn(PL_statcache.st_size);
#else
- mPUSHi(PL_statcache.st_size);
+ mPUSHu(PL_statcache.st_size);
#endif
#ifdef BIG_TIME
mPUSHn(PL_statcache.st_atime);
@@ -3527,7 +3527,7 @@ PP(pp_ftis)
#if Off_t_size > IVSIZE
sv_setnv(TARG, (NV)PL_statcache.st_size);
#else
- sv_setiv(TARG, (IV)PL_statcache.st_size);
+ sv_setuv(TARG, (UV)PL_statcache.st_size);
#endif
break;
case OP_FTMTIME: |
Can you look up the type of |
In |
The behavior we're observing is strongly suggesting the type of We're already detecting the signedness of |
I'm also curious of the cause, but |
st_dev_sign is |
I've come up against a bit of a wall while porting Perl to WASM (using wasi-sdk/wasi-libc). I've gotten everything working, except for an issue with files over 2GB - when stat'ing them, the file size comes back wrong:
The negative size (-1073741824) suggests we're hitting a 32-bit integer overflow, which is odd since the build is configured with both
use64bitint=define
anduse64bitall=define
. I've double-checked thativsize
is set to 8 andlseeksize
is 8 in the config.Before opening this issue I confirmed it wasn't an upstream issue in clang or wasi-libc. I'm attaching my full perl config output below.
I understand this may not be a priority issue since wasm32-wasi isn't an official target yet, but I'd appreciate any guidance on where I can look within Perl's source to potentially patch this, or if there are any specific flags in my configuration hint file I should try.
Full Configuration
While the above configuration says 5.41.7, I've also tested on 5.40.0 and the issue persist
The only other relevant issue I could find was this one from 1999.
The text was updated successfully, but these errors were encountered: