- 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);
- SvCUR_set(targ, len);
+ else if (size > 8) {
+ int n = size/8;
+ if (offset > Size_t_MAX / n - 1) /* would overflow */
+ Perl_croak_nocontext("Out of memory!");
+ offset *= n;
+ }
+
+ len = (bitoffs + size + 7)/8; /* required number of bytes */
+ if (targlen < offset || targlen - offset < len) {
+ STRLEN newlen = offset > Size_t_MAX - len - 1 ? /* avoid overflow */
+ Size_t_MAX : offset + len + 1;
+ s = (unsigned char*)SvGROW(targ, newlen);
+ (void)memzero((char *)(s + targlen), newlen - targlen);
+ SvCUR_set(targ, newlen - 1);