diff options
author | Stefan Esser <sesser@php.net> | 2004-11-28 12:44:28 +0000 |
---|---|---|
committer | Stefan Esser <sesser@php.net> | 2004-11-28 12:44:28 +0000 |
commit | 6d98fc38b53c0ce803bf5cc8de05e2083eb6cd41 (patch) | |
tree | 9b993fd85fecd34bff547c15b3dd5c8e52b127f0 /ext/standard/pack.c | |
parent | e0e157e6de4799c3cc00952fffc353c34e48459e (diff) | |
download | php-git-6d98fc38b53c0ce803bf5cc8de05e2083eb6cd41.tar.gz |
Fixed: removed possible integer over-/underflows
Diffstat (limited to 'ext/standard/pack.c')
-rw-r--r-- | ext/standard/pack.c | 30 |
1 files changed, 23 insertions, 7 deletions
diff --git a/ext/standard/pack.c b/ext/standard/pack.c index d45f9817d1..f41695c562 100644 --- a/ext/standard/pack.c +++ b/ext/standard/pack.c @@ -60,6 +60,13 @@ #include <netinet/in.h> #endif +#define INC_OUTPUTPOS(a,b) \ + if ((a) < 0 || ((INT_MAX - outputpos)/(b)) < (a)) { \ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: integer overflow in format string", code); \ + RETURN_FALSE; \ + } \ + outputpos += (a)*(b); + /* Whether machine is little endian */ char machine_little_endian; @@ -243,7 +250,7 @@ PHP_FUNCTION(pack) switch ((int) code) { case 'h': case 'H': - outputpos += (arg + 1) / 2; /* 4 bit per arg */ + INC_OUTPUTPOS((arg + 1) / 2,1) /* 4 bit per arg */ break; case 'a': @@ -251,34 +258,34 @@ PHP_FUNCTION(pack) case 'c': case 'C': case 'x': - outputpos += arg; /* 8 bit per arg */ + INC_OUTPUTPOS(arg,1) /* 8 bit per arg */ break; case 's': case 'S': case 'n': case 'v': - outputpos += arg * 2; /* 16 bit per arg */ + INC_OUTPUTPOS(arg,2) /* 16 bit per arg */ break; case 'i': case 'I': - outputpos += arg * sizeof(int); + INC_OUTPUTPOS(arg,sizeof(int)) break; case 'l': case 'L': case 'N': case 'V': - outputpos += arg * 4; /* 32 bit per arg */ + INC_OUTPUTPOS(arg,4) /* 32 bit per arg */ break; case 'f': - outputpos += arg * sizeof(float); + INC_OUTPUTPOS(arg,sizeof(float)) break; case 'd': - outputpos += arg * sizeof(double); + INC_OUTPUTPOS(arg,sizeof(double)) break; case 'X': @@ -647,6 +654,11 @@ PHP_FUNCTION(unpack) sprintf(n, "%.*s", namelen, name); } + if (size != 0 && size != -1 && INT_MAX - size + 1 < inputpos) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: integer overflow", type); + inputpos = 0; + } + if ((inputpos + size) <= inputlen) { switch ((int) type) { case 'a': @@ -817,6 +829,10 @@ PHP_FUNCTION(unpack) } inputpos += size; + if (inputpos < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: outside of string", type); + inputpos = 0; + } } else if (arg < 0) { /* Reached end of input for '*' repeater */ break; |