summaryrefslogtreecommitdiff
path: root/ext/standard/pack.c
diff options
context:
space:
mode:
authorStefan Esser <sesser@php.net>2004-11-28 12:44:28 +0000
committerStefan Esser <sesser@php.net>2004-11-28 12:44:28 +0000
commit6d98fc38b53c0ce803bf5cc8de05e2083eb6cd41 (patch)
tree9b993fd85fecd34bff547c15b3dd5c8e52b127f0 /ext/standard/pack.c
parente0e157e6de4799c3cc00952fffc353c34e48459e (diff)
downloadphp-git-6d98fc38b53c0ce803bf5cc8de05e2083eb6cd41.tar.gz
Fixed: removed possible integer over-/underflows
Diffstat (limited to 'ext/standard/pack.c')
-rw-r--r--ext/standard/pack.c30
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;