fix for ConvToString
When we do CastString on an object, the ConvObjToStr helper may throw if it does not have a __toString() function. When spilling the stack before calling the helper, we must push back the popped object. Also convObjToString helper should not decref its object if the conversion failed.
Esse commit está contido em:
@@ -102,9 +102,19 @@ int64_t convStrToDblHelper(const StringData* s) {
|
||||
}
|
||||
|
||||
int64_t convCellToDblHelper(TypedValue tv) {
|
||||
tvCastToDoubleInPlace(&tv); // consumes a ref on counted values
|
||||
// but not if an exception happens. (REVIEW)
|
||||
return tv.m_data.num;
|
||||
try {
|
||||
tvCastToDoubleInPlace(&tv); // consumes a ref on counted values
|
||||
// but not if an exception happens. (REVIEW)
|
||||
return tv.m_data.num;
|
||||
} catch (...) {
|
||||
// spill tv back to stack. unwinder
|
||||
// will take care of decreffing it.
|
||||
VMRegAnchor _;
|
||||
TypedValue* spillSlot = (TypedValue *)vmsp();
|
||||
spillSlot->m_data.num = tv.m_data.num;
|
||||
spillSlot->m_type = tv.m_type;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
int64_t convArrToIntHelper(ArrayData* a) {
|
||||
@@ -122,9 +132,19 @@ int64_t convStrToIntHelper(const StringData* s) {
|
||||
}
|
||||
|
||||
int64_t convCellToIntHelper(TypedValue tv) {
|
||||
tvCastToInt64InPlace(&tv); // consumes a ref on counted values
|
||||
// but not if an exception happens. (REVIEW)
|
||||
return tv.m_data.num;
|
||||
try {
|
||||
tvCastToInt64InPlace(&tv); // consumes a ref on counted values
|
||||
// but not if an exception happens. (REVIEW)
|
||||
return tv.m_data.num;
|
||||
} catch (...) {
|
||||
// spill tv back to stack. unwinder
|
||||
// will take care of decreffing it.
|
||||
VMRegAnchor _;
|
||||
TypedValue* spillSlot = (TypedValue *)vmsp();
|
||||
spillSlot->m_data.num = tv.m_data.num;
|
||||
spillSlot->m_type = tv.m_type;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
ObjectData* convCellToObjHelper(TypedValue tv) {
|
||||
@@ -157,11 +177,16 @@ StringData* convObjToStrHelper(ObjectData* o) {
|
||||
try {
|
||||
auto s = o->t___tostring();
|
||||
auto r = s.get();
|
||||
o->decRefCount();
|
||||
decRefObj(o);
|
||||
if (!r->isStatic()) r->incRefCount();
|
||||
return r;
|
||||
} catch (...) {
|
||||
o->decRefCount();
|
||||
// spill object back to stack. unwinder
|
||||
// will take care of decreffing it.
|
||||
VMRegAnchor _;
|
||||
TypedValue* spillSlot = (TypedValue *)vmsp();
|
||||
spillSlot->m_data.pobj = o;
|
||||
spillSlot->m_type = KindOfObject;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php ;
|
||||
|
||||
class X {
|
||||
function not__toString() { throw new Exception('boom'); }
|
||||
}
|
||||
|
||||
function error_handler() {
|
||||
throw new Exception("user error handler");
|
||||
}
|
||||
//set_error_handler('error_handler');
|
||||
|
||||
function foo($x) {
|
||||
return $x;
|
||||
}
|
||||
|
||||
function testStr($x) {
|
||||
return foo((string)$x);
|
||||
}
|
||||
|
||||
function testInt($x) {
|
||||
return foo((int)$x);
|
||||
}
|
||||
|
||||
function testDbl($x) {
|
||||
return foo((double)$x);
|
||||
}
|
||||
|
||||
echo "test int\n";
|
||||
|
||||
try {
|
||||
testInt(new X);
|
||||
} catch (Exception $e) {
|
||||
var_dump($e->getMessage());
|
||||
}
|
||||
|
||||
echo "test dbl\n";
|
||||
|
||||
try {
|
||||
testDbl(new X);
|
||||
} catch (Exception $e) {
|
||||
var_dump($e->getMessage());
|
||||
}
|
||||
|
||||
echo "test str\n";
|
||||
|
||||
try {
|
||||
testStr(new X);
|
||||
} catch (Exception $e) {
|
||||
var_dump($e->getMessage());
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
test int
|
||||
HipHop Notice: Object of class X could not be converted to int in %s on line 21
|
||||
test dbl
|
||||
HipHop Notice: Object of class X could not be converted to int in %s on line 25
|
||||
test str
|
||||
HipHop Fatal error: Bad type conversion: X::__toString() was not defined. in %s on line 17
|
||||
@@ -1,19 +0,0 @@
|
||||
<?php ;
|
||||
|
||||
class X {
|
||||
function not__toString() { throw new Exception('boom'); }
|
||||
}
|
||||
|
||||
function foo($x) {
|
||||
return $x;
|
||||
}
|
||||
|
||||
function test($x) {
|
||||
return foo((string)$x);
|
||||
}
|
||||
|
||||
try {
|
||||
test(new X);
|
||||
} catch (Exception $e) {
|
||||
var_dump($e->getMessage());
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
HipHop Fatal error: Bad type conversion: X::__toString() was not defined. in %s on line 12
|
||||
Referência em uma Nova Issue
Bloquear um usuário