diff options
author | Marcus Holland-Moritz <mhx-perl@gmx.net> | 2006-12-10 23:32:32 +0100 |
---|---|---|
committer | Rafael Garcia-Suarez <rgarciasuarez@gmail.com> | 2006-12-11 10:28:13 +0000 |
commit | bbb8a7e0703e09f15457e855696dbeebcd270517 (patch) | |
tree | c3f4c0085198a70c8514a7a3a72d1cc450c5d77f /doop.c | |
parent | a52aaefaf122bfd3376b8d1122b5d51398b8aff2 (diff) | |
download | perl-bbb8a7e0703e09f15457e855696dbeebcd270517.tar.gz |
Re: [perl #41065] Out of memory!, while extending scalar
Message-ID: <20061210223232.0f3a5318@r2d2>
p4raw-id: //depot/perl@29506
Diffstat (limited to 'doop.c')
-rw-r--r-- | doop.c | 37 |
1 files changed, 23 insertions, 14 deletions
@@ -726,7 +726,7 @@ UV Perl_do_vecget(pTHX_ SV *sv, I32 offset, I32 size) { dVAR; - STRLEN srclen, len, uoffset; + STRLEN srclen, len, uoffset, bitoffs = 0; const unsigned char *s = (const unsigned char *) SvPV_const(sv, srclen); UV retnum = 0; @@ -738,13 +738,20 @@ Perl_do_vecget(pTHX_ SV *sv, I32 offset, I32 size) if (SvUTF8(sv)) (void) Perl_sv_utf8_downgrade(aTHX_ sv, TRUE); - uoffset = offset*size; /* turn into bit offset */ - len = (uoffset + size + 7) / 8; /* required number of bytes */ + if (size < 8) { + bitoffs = ((offset%8)*size)%8; + uoffset = offset/(8/size); + } + else if (size > 8) + uoffset = offset*(size/8); + else + uoffset = offset; + + len = uoffset + (bitoffs + size + 7)/8; /* required number of bytes */ if (len > srclen) { if (size <= 8) retnum = 0; else { - uoffset >>= 3; /* turn into byte offset */ if (size == 16) { if (uoffset >= srclen) retnum = 0; @@ -821,9 +828,8 @@ Perl_do_vecget(pTHX_ SV *sv, I32 offset, I32 size) } } else if (size < 8) - retnum = (s[uoffset >> 3] >> (uoffset & 7)) & ((1 << size) - 1); + retnum = (s[uoffset] >> bitoffs) & ((1 << size) - 1); else { - uoffset >>= 3; /* turn into byte offset */ if (size == 8) retnum = s[uoffset]; else if (size == 16) @@ -865,7 +871,7 @@ void Perl_do_vecset(pTHX_ SV *sv) { dVAR; - register I32 offset; + register I32 offset, bitoffs = 0; register I32 size; register unsigned char *s; register UV lval; @@ -894,8 +900,14 @@ Perl_do_vecset(pTHX_ SV *sv) if (size < 1 || (size & (size-1))) /* size < 1 or not a power of two */ Perl_croak(aTHX_ "Illegal number of bits in vec"); - offset *= size; /* turn into bit offset */ - len = (offset + size + 7) / 8; /* required number of bytes */ + if (size < 8) { + bitoffs = ((offset%8)*size)%8; + offset /= 8/size; + } + else if (size > 8) + offset *= size/8; + + len = offset + (bitoffs + size + 7)/8; /* required number of bytes */ if (len > targlen) { s = (unsigned char*)SvGROW(targ, len + 1); (void)memzero((char *)(s + targlen), len - targlen + 1); @@ -904,14 +916,11 @@ Perl_do_vecset(pTHX_ SV *sv) if (size < 8) { mask = (1 << size) - 1; - size = offset & 7; lval &= mask; - offset >>= 3; /* turn into byte offset */ - s[offset] &= ~(mask << size); - s[offset] |= lval << size; + s[offset] &= ~(mask << bitoffs); + s[offset] |= lval << bitoffs; } else { - offset >>= 3; /* turn into byte offset */ if (size == 8) s[offset ] = (U8)( lval & 0xff); else if (size == 16) { |