第零章 WebKit 霸气修改

js容错机制修改

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(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(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(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(slot.cachedOffset());
        }
    }

    LLINT_RETURN(slot.getValue(exec, ident));
}

跨域修改

SecurityOrigin.cpp:

修改1

修改2

一种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 whitelist;
    Vector 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); //获取根部节点
    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;
}

你可能感兴趣的:(第零章 WebKit 霸气修改)