Bug 1500805 Part 4 - Watch for bogus pointers when checking for constant compile time strings, r=mccr8.

--HG--
extra : rebase_source : 7517295161e729dabdeae940b8ba4569df8f7754
This commit is contained in:
Brian Hackett 2018-10-21 15:04:18 -06:00
Родитель cb7d3c281c
Коммит 650805afa6
3 изменённых файлов: 41 добавлений и 30 удалений

Просмотреть файл

@ -662,6 +662,17 @@ HandleDirtyMemoryFault(uint8_t* aAddress)
return true;
}
bool
MemoryRangeIsTracked(void* aAddress, size_t aSize)
{
for (uint8_t* ptr = PageBase(aAddress); ptr < (uint8_t*) aAddress + aSize; ptr += PageSize) {
if (!IsTrackedAddress(ptr, nullptr)) {
return false;
}
}
return true;
}
void
UnrecoverableSnapshotFailure()
{

Просмотреть файл

@ -50,6 +50,11 @@ void RegisterAllocatedMemory(void* aBaseAddress, size_t aSize, MemoryKind aKind)
// been reached.
void AddInitialUntrackedMemoryRegion(uint8_t* aBase, size_t aSize);
// Return whether a range of memory is in a tracked region. This excludes
// memory that was allocated after the last checkpoint and is not write
// protected.
bool MemoryRangeIsTracked(void* aAddress, size_t aSize);
// Initialize the memory snapshots system.
void InitializeMemorySnapshots();

Просмотреть файл

@ -695,20 +695,6 @@ ReplayInvokeCallback(size_t aCallbackId)
// Middleman Call Helpers
///////////////////////////////////////////////////////////////////////////////
static bool
TestObjCObjectClass(id aObj, const char* aName)
{
Class cls = object_getClass(aObj);
while (cls) {
const char* className = class_getName(cls);
if (!strcmp(className, aName)) {
return true;
}
cls = class_getSuperclass(cls);
}
return false;
}
// Inputs that originate from static data in the replaying process itself
// rather than from previous middleman calls.
enum class ObjCInputKind {
@ -716,6 +702,14 @@ enum class ObjCInputKind {
ConstantString,
};
// Internal layout of a constant compile time CFStringRef.
struct CFConstantString {
Class mClass;
size_t mStuff;
char* mData;
size_t mLength;
};
// Capture an Objective C or CoreFoundation input to a call, which may come
// either from another middleman call, or from static data in the replaying
// process.
@ -759,22 +753,23 @@ Middleman_ObjCInput(MiddlemanCallContext& aCx, id* aThingPtr)
}
// Watch for constant compile time strings baked into the generated code or
// stored in system libraries. We can crash here if the object came from
// e.g. a replayed pointer from the recording, as can happen if not enough
// redirections have middleman call hooks. We could do better here to make
// sure the pointer looks like it could be a constant string, but it seems
// better and simpler to crash more reliably here than mask problems due to
// missing middleman call hooks.
if (TestObjCObjectClass(*aThingPtr, "NSString")) {
AutoPassThroughThreadEvents pt;
CFIndex len = CFStringGetLength((CFStringRef)*aThingPtr);
InfallibleVector<UniChar> buffer;
buffer.appendN(0, len);
CFStringGetCharacters((CFStringRef)*aThingPtr, { 0, len }, buffer.begin());
aCx.WriteInputScalar((size_t) ObjCInputKind::ConstantString);
aCx.WriteInputScalar(len);
aCx.WriteInputBytes(buffer.begin(), len * sizeof(UniChar));
return;
// stored in system libraries. Be careful when accessing the pointer as in
// the case where a middleman call hook for a function is missing the
// pointer could have originated from the recording and its address may not
// be mapped. In this case we would rather gracefully recover and fail to
// paint, instead of crashing.
if (MemoryRangeIsTracked(*aThingPtr, sizeof(CFConstantString))) {
CFConstantString* str = (CFConstantString*) *aThingPtr;
if (str->mClass == objc_lookUpClass("__NSCFConstantString") &&
str->mLength <= 4096 && // Sanity check.
MemoryRangeIsTracked(str->mData, str->mLength)) {
InfallibleVector<UniChar> buffer;
NS_ConvertUTF8toUTF16 converted(str->mData, str->mLength);
aCx.WriteInputScalar((size_t) ObjCInputKind::ConstantString);
aCx.WriteInputScalar(str->mLength);
aCx.WriteInputBytes(converted.get(), str->mLength * sizeof(UniChar));
return;
}
}
aCx.MarkAsFailed();