第零章 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<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:

修改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<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); //获取根部节点
    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;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,441评论 25 707
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,571评论 18 399
  • 【转载】CSDN - 张林blog http://blog.csdn.net/XIAOZHUXMEN/articl...
    竿牍阅读 3,479评论 1 14
  • 找到真我 成为它 成就它 才是真正的爱自已啊 什么是真我呢 就是真实的自已啊 如何找到真我呢 那就去了解自...
    雪莉诗话阅读 339评论 0 1
  • 人要是能在世上活得好,活得幸福,不会寻找神的,正因为人活得不好,所以寻找。因为不知道活得不好的原因就是和神分开,所...
    MO若耶阅读 229评论 0 2