js容錯(cuò)機(jī)制修改
JITExceptions.cpp:
//未修改前代碼
void genericUnwind(VM* vm, ExecState* callFrame, JSValue exceptionValue)
{
RELEASE_ASSERT(exceptionValue);
HandlerInfo* handler = vm->interpreter->unwind(callFrame, exceptionValue); // This may update callFrame.
void* catchRoutine;
Instruction* catchPCForInterpreter = 0;
if (handler) {
catchPCForInterpreter = &callFrame->codeBlock()->instructions()[handler->target];
#if ENABLE(JIT)
catchRoutine = handler->nativeCode.executableAddress();
#else
catchRoutine = catchPCForInterpreter->u.pointer;
#endif
} else
catchRoutine = LLInt::getCodePtr(returnFromJavaScript);
vm->callFrameForThrow = callFrame;
vm->targetMachinePCForThrow = catchRoutine;
vm->targetInterpreterPCForThrow = catchPCForInterpreter;
RELEASE_ASSERT(catchRoutine);
}
//修改之后代碼
void genericUnwind(VM* vm, ExecState* callFrame, JSValue exceptionValue)
{
RELEASE_ASSERT(exceptionValue);
ExecState* saveCallFrame = callFrame;
HandlerInfo* handler = vm->interpreter->unwind(callFrame, exceptionValue); // This may update callFrame.
void* catchRoutine;
Instruction* catchPCForInterpreter = 0;
if (handler) {
catchPCForInterpreter = &callFrame->codeBlock()->instructions()[handler->target];
#if ENABLE(JIT)
catchRoutine = handler->nativeCode.executableAddress();
#else
catchRoutine = catchPCForInterpreter->u.pointer;
#endif
}
else{
#ifndef USE_UTSTARCOM
catchRoutine = LLInt::getCodePtr(returnFromJavaScript);
#else
Instruction* vpc = saveCallFrame->currentVPC() - 1;
unsigned int line = 0, column = 0;
if (vm->exceptionStack().size() > 0) {
String file = vm->exceptionStack()[0].friendlySourceURL();
ULOG("[JS] catch js exception file:%s(%d)", file.ascii().data(), vm->exceptionStack()[0].lineOffset + vm->exceptionStack()[0].firstLineColumnOffset);
}
ULOG("[JS] catch js exception op len:%d", opcodeLength(vm->interpreter->getOpcodeID(vpc->u.opcode)));
if (opcodeLength(vm->interpreter->getOpcodeID(vpc->u.opcode)) == 0){
catchRoutine = LLInt::getCodePtr(returnFromJavaScript);
goto END;
}
catchPCForInterpreter = vpc + opcodeLength(vm->interpreter->getOpcodeID(vpc->u.opcode));
#if ENABLE(JIT)
catchRoutine = handler->nativeCode.executableAddress();
#else
catchRoutine = catchPCForInterpreter->u.pointer;
#endif
ULOG("[JS] catch js exception 2");
vm->clearException();
vm->clearExceptionStack();
#endif
}
END:
vm->callFrameForThrow = callFrame;
vm->targetMachinePCForThrow = catchRoutine;
vm->targetInterpreterPCForThrow = catchPCForInterpreter;
RELEASE_ASSERT(catchRoutine);
}
LLIntSlowPaths.cpp:
//未修改前代碼
LLINT_SLOW_PATH_DECL(slow_path_handle_exception)
{
LLINT_BEGIN_NO_SET_PC();
ASSERT(vm.exception());
genericUnwind(&vm, exec, vm.exception());
LLINT_END_IMPL();
}
//修改之后代碼
LLINT_SLOW_PATH_DECL(slow_path_handle_exception)
{
LLINT_BEGIN_NO_SET_PC();
ASSERT(vm.exception());
genericUnwind(&vm, exec, vm.exception());
#ifdef USE_UTSTARCOM
if (vm.exception() == JSValue()){
Instruction* vpc = exec->currentVPC() - 1;
if (opcodeLength(exec->interpreter()->getOpcodeID(vpc->u.opcode)) == 0){
goto END;
}
pc = vpc + opcodeLength(exec->interpreter()->getOpcodeID(vpc->u.opcode));
}
END:
#endif
LLINT_END_IMPL();
}
//修改之前代碼
LLINT_SLOW_PATH_DECL(slow_path_get_from_scope)
{
LLINT_BEGIN();
const Identifier& ident = exec->codeBlock()->identifier(pc[3].u.operand);
JSObject* scope = jsCast<JSObject*>(LLINT_OP(2).jsValue());
ResolveModeAndType modeAndType(pc[4].u.operand);
PropertySlot slot(scope);
if (!scope->getPropertySlot(exec, ident, slot)) {
if (modeAndType.mode() == ThrowIfNotFound)
LLINT_RETURN(exec->vm().throwException(exec, createUndefinedVariableError(exec, ident)));
LLINT_RETURN(jsUndefined());
}
// Covers implicit globals. Since they don't exist until they first execute, we didn't know how to cache them at compile time.
if (slot.isCacheableValue() && slot.slotBase() == scope && scope->structure()->propertyAccessesAreCacheable()) {
if (modeAndType.type() == GlobalProperty || modeAndType.type() == GlobalPropertyWithVarInjectionChecks) {
CodeBlock* codeBlock = exec->codeBlock();
ConcurrentJITLocker locker(codeBlock->m_lock);
pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), scope->structure());
pc[6].u.pointer = reinterpret_cast<void*>(slot.cachedOffset());
}
}
LLINT_RETURN(slot.getValue(exec, ident));
}
//修改之后代碼
LLINT_SLOW_PATH_DECL(slow_path_get_from_scope)
{
LLINT_BEGIN();
const Identifier& ident = exec->codeBlock()->identifier(pc[3].u.operand);
JSObject* scope = jsCast<JSObject*>(LLINT_OP(2).jsValue());
ResolveModeAndType modeAndType(pc[4].u.operand);
PropertySlot slot(scope);
if (!scope->getPropertySlot(exec, ident, slot)) {
#ifndef USE_UTSTARCOM
if (modeAndType.mode() == ThrowIfNotFound)
LLINT_RETURN(exec->vm().throwException(exec, createUndefinedVariableError(exec, ident)));
#endif
LLINT_RETURN(jsUndefined());
}
// Covers implicit globals. Since they don't exist until they first execute, we didn't know how to cache them at compile time.
if (slot.isCacheableValue() && slot.slotBase() == scope && scope->structure()->propertyAccessesAreCacheable()) {
if (modeAndType.type() == GlobalProperty || modeAndType.type() == GlobalPropertyWithVarInjectionChecks) {
CodeBlock* codeBlock = exec->codeBlock();
ConcurrentJITLocker locker(codeBlock->m_lock);
pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), scope->structure());
pc[6].u.pointer = reinterpret_cast<void*>(slot.cachedOffset());
}
}
LLINT_RETURN(slot.getValue(exec, ident));
}
跨域修改
SecurityOrigin.cpp:
一種js注入邏輯(通過讀取xml形式)
int WebFrame_js_css_inject(void* handle, const char* filename)
{
int ret = 0;
WebView* view = (WebView*)handle;
if (!handle)
return -1;
if (!filename)
return -1;
URL url = URL(ParsedURLString, "JsCssInject");
Vector<String> whitelist;
Vector<String> blacklist;
int isJS = 1;
int itemChildNum = 0;
JsCssInjectTime injectTime = JsCssInjectAtTop;
xmlDocPtr doc;
xmlNodePtr rootNode = NULL;
xmlNodePtr childNode = NULL;
xmlNodePtr itemNodePtr = NULL;
xmlNodePtr itemChildPtr = NULL;
xmlNodePtr urlNodePtr = NULL;
xmlKeepBlanksDefault(0);
doc = xmlReadFile(filename, "UTF8", XML_PARSE_RECOVER); //讀取xml文件
if (doc==NULL){
fprintf(stderr,"Document not parsed successfully.\n");
return -1;
}
rootNode = xmlDocGetRootElement(doc); //獲取根部節(jié)點(diǎn)
if (NULL == rootNode){
fprintf(stderr,"empty document\n");
xmlFreeDoc(doc);
return -1;
}
if (xmlStrcmp(rootNode->name, BAD_CAST "resource")) {
fprintf(stderr,"document of the wrong type, root node != InjectFile");
xmlFreeDoc(doc);
return -1;
}
childNode = rootNode->children;
while (childNode != NULL) {
if (!xmlStrcmp(childNode->name, BAD_CAST "item"))
itemNodePtr = childNode;
if (itemNodePtr != NULL) {
/* 清除黑白名單url*/
whitelist.clear();
blacklist.clear();
char *source = NULL;
itemChildNum = 0;
itemChildPtr = itemNodePtr->children;
while (itemChildPtr != NULL) {
if (!xmlStrcmp(itemChildPtr->name, BAD_CAST "whitelist")) {
urlNodePtr = itemChildPtr->children;
while (urlNodePtr != NULL) {
if (!xmlStrcmp(urlNodePtr->name, BAD_CAST "url")) {
char *value = (char*)xmlNodeGetContent(urlNodePtr);
whitelist.append(value);
xmlFree(value);
}
urlNodePtr = urlNodePtr->next;
}
itemChildNum++;
} else if (!xmlStrcmp(itemChildPtr->name, BAD_CAST "blacklist")) {
urlNodePtr = itemChildPtr->children;
while (urlNodePtr != NULL) {
if (!xmlStrcmp(urlNodePtr->name, BAD_CAST "url")) {
char *value = (char*)xmlNodeGetContent(urlNodePtr);
blacklist.append(value);
xmlFree(value);
}
urlNodePtr = urlNodePtr->next;
}
itemChildNum++;
} else if ((!xmlStrcmp(itemChildPtr->name, BAD_CAST "type"))) {
xmlChar *value = xmlNodeGetContent(itemChildPtr);
if(!xmlStrcasecmp(value, BAD_CAST "css"))
isJS = 0;
else if (!xmlStrcasecmp(value, BAD_CAST "js"))
isJS = 1;
else {
xmlFree(value);
break;
}
itemChildNum++;
xmlFree(value);
} else if ((!xmlStrcmp(itemChildPtr->name, BAD_CAST "position"))) {
xmlChar *value = xmlNodeGetContent(itemChildPtr);
if (!xmlStrcasecmp(value, BAD_CAST "top"))
injectTime = JsCssInjectAtTop;
else if (!xmlStrcasecmp(value, BAD_CAST "bottom"))
injectTime = JsCssInjectAtBottom;
else {
xmlFree(value);
break;
}
itemChildNum++;
xmlFree(value);
} else if ((!xmlStrcmp(itemChildPtr->name, BAD_CAST "file"))) {
char* value = (char*)xmlNodeGetContent(itemChildPtr);
if (!common_fileExists(value)) {
xmlFree(value);
break;
}
PlatformFileHandle fileHandle;
fileHandle = common_openFile(value, 0);
if (fileHandle == invalidPlatformFileHandle) {
xmlFree(value);
break;
}
long long filesize;
if (!common_getFileSize(value, filesize)) {
xmlFree(value);
break;
}
source = (char *)malloc((filesize + 1) * sizeof(char));
memset(source, 0, (filesize + 1) * sizeof(char));
if (!common_readFromFile(fileHandle, source, filesize)) {
xmlFree(value);
break;
}
itemChildNum++;
xmlFree(value);
}
itemChildPtr = itemChildPtr->next;
}
if (itemChildNum == 5) {
if (isJS)
view->addUserScript(String(source), url, whitelist, blacklist, injectTime);
else
view->addUserStyleSheet(String(source), url, whitelist, blacklist, injectTime);
}
if (source)
free(source);
}
itemNodePtr = NULL;
childNode = childNode->next;
}
xmlFreeDoc(doc);
xmlCleanupParser();
return ret ? 0 : -1;
}