Tighten tvIsPlausible() checks

I've found several bugs recently due to the TypedValue plausible
check being too loose.  Our DataType enum values are now sparse,
and we miss garbage that happens to fall inside the [-10, 127]
range, which is >50% of possible garbage values.
Esse commit está contido em:
smith
2013-03-28 06:48:50 -07:00
commit de Sara Golemon
commit 55c20f79c1
4 arquivos alterados com 42 adições e 12 exclusões
+30
Ver Arquivo
@@ -205,5 +205,35 @@ void tvCastToObjectInPlace(TypedValue* tv) {
tv->m_data.pobj->incRefCount();
}
bool tvIsPlausible(const TypedValue* tv) {
if (!tv) return false;
auto okPtr = [](void* ptr) {
return ptr && (uintptr_t(ptr) % sizeof(ptr) == 0);
};
switch (tv->m_type) {
case KindOfUninit:
case KindOfNull:
return true;
case KindOfBoolean:
return tv->m_data.num == 0 || tv->m_data.num == 1;
case KindOfInt64:
case KindOfDouble:
return true;
case KindOfStaticString:
return okPtr(tv->m_data.pstr) && tv->m_data.pstr->isStatic();
case KindOfString:
case KindOfArray:
return okPtr(tv->m_data.parr) &&
is_refcount_realistic(tv->m_data.parr->getCount());
case KindOfObject:
return okPtr(tv->m_data.pobj) && !tv->m_data.pobj->isStatic();
case KindOfRef:
return okPtr(tv->m_data.pref) &&
tv->m_data.pref->tv()->m_type != KindOfRef;
default:
return false;
}
}
///////////////////////////////////////////////////////////////////////////////
}
+1 -7
Ver Arquivo
@@ -48,13 +48,7 @@ inline TypedValue tv(DataType type, Data data) {
// Assumes 'IS_REFCOUNTED_TYPE(type)'
void tvDecRefHelper(DataType type, uint64_t datum);
inline bool tvIsPlausibleType(DataType type) {
return type >= MinDataType && type < MaxNumDataTypes;
}
inline bool tvIsPlausible(const TypedValue* tv) {
return tvIsPlausibleType(tv->m_type);
}
bool tvIsPlausible(const TypedValue* tv);
inline bool tvWillBeReleased(TypedValue* tv) {
return IS_REFCOUNTED_TYPE(tv->m_type) &&
+3 -3
Ver Arquivo
@@ -4638,7 +4638,7 @@ inline void OPTBLD_INLINE VMExecutionContext::iopCGetG(PC& pc) {
} else { \
tvReadCell(val, output); \
} \
m_stack.popC(); \
m_stack.popA(); \
SPROP_OP_POSTLUDE \
} while (0)
@@ -4769,7 +4769,7 @@ inline void OPTBLD_INLINE VMExecutionContext::iopIssetS(PC& pc) {
} else {
e = isset(tvAsCVarRef(val));
}
m_stack.popC();
m_stack.popA();
output->m_data.num = e;
output->m_type = KindOfBoolean;
SPROP_OP_POSTLUDE
@@ -4898,7 +4898,7 @@ inline void OPTBLD_INLINE VMExecutionContext::iopEmptyS(PC& pc) {
} else {
e = empty(tvAsCVarRef(val));
}
m_stack.popC();
m_stack.popA();
output->m_data.num = e;
output->m_type = KindOfBoolean;
SPROP_OP_POSTLUDE
+8 -2
Ver Arquivo
@@ -543,6 +543,12 @@ public:
m_top++;
}
inline void ALWAYS_INLINE popA() {
assert(m_top != m_base);
assert(m_top->m_type == KindOfClass);
m_top++;
}
inline void ALWAYS_INLINE popV() {
assert(m_top != m_base);
assert(m_top->m_type == KindOfRef);
@@ -553,7 +559,7 @@ public:
inline void ALWAYS_INLINE popTV() {
assert(m_top != m_base);
assert(tvIsPlausible(m_top));
assert(m_top->m_type == KindOfClass || tvIsPlausible(m_top));
tvRefcountedDecRef(m_top);
m_top++;
}
@@ -704,7 +710,7 @@ public:
pushObjectNoRc(o);
o->incRefCount();
}
inline void ALWAYS_INLINE nalloc(size_t n) {
assert((uintptr_t)&m_top[-n] <= (uintptr_t)m_base);
m_top -= n;