summaryrefslogtreecommitdiff
path: root/doop.c
diff options
context:
space:
mode:
authorMarcus Holland-Moritz <mhx-perl@gmx.net>2006-12-10 23:32:32 +0100
committerRafael Garcia-Suarez <rgarciasuarez@gmail.com>2006-12-11 10:28:13 +0000
commitbbb8a7e0703e09f15457e855696dbeebcd270517 (patch)
treec3f4c0085198a70c8514a7a3a72d1cc450c5d77f /doop.c
parenta52aaefaf122bfd3376b8d1122b5d51398b8aff2 (diff)
downloadperl-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.c37
1 files changed, 23 insertions, 14 deletions
diff --git a/doop.c b/doop.c
index 16204653b0..530fef2b92 100644
--- a/doop.c
+++ b/doop.c
@@ -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) {