Skip to content

Commit e65adc9

Browse files
committed
Fix ubsan violation in parse_iv2
This fixes two issues: * Negative the value in an unsigned type to avoid signed overflow. * Treat -0 as 0 rather than an invalid number that gets converted to ZEND_LONG_MIN.
1 parent 9c89f43 commit e65adc9

File tree

2 files changed

+14
-2
lines changed

2 files changed

+14
-2
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
--TEST--
2+
Negative parse_iv2 edge cases
3+
--FILE--
4+
<?php
5+
6+
var_dump(unserialize('i:-9223372036854775808;'));
7+
var_dump(unserialize('i:-0;'));
8+
9+
?>
10+
--EXPECT--
11+
int(-9223372036854775808)
12+
int(0)

ext/standard/var_unserializer.re

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -357,12 +357,12 @@ static inline zend_long parse_iv2(const unsigned char *p, const unsigned char **
357357
|| (SIZEOF_ZEND_LONG == 4
358358
&& UNEXPECTED(p - start == MAX_LENGTH_OF_LONG - 1)
359359
&& UNEXPECTED(*start > '2'))
360-
|| UNEXPECTED(result - neg > ZEND_LONG_MAX)) {
360+
|| UNEXPECTED(result > ZEND_LONG_MAX + neg)) {
361361
php_error_docref(NULL, E_WARNING, "Numerical result out of range");
362362
return (!neg) ? ZEND_LONG_MAX : ZEND_LONG_MIN;
363363
}
364364

365-
return (!neg) ? (zend_long)result : -(zend_long)result;
365+
return (zend_long) ((!neg) ? result : -result);
366366
}
367367

368368
static inline zend_long parse_iv(const unsigned char *p)

0 commit comments

Comments
 (0)