Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
michael@0 | 1 | /* -*- Mode: Javascript; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
michael@0 | 2 | |
michael@0 | 3 | "use strict"; |
michael@0 | 4 | |
michael@0 | 5 | // Ignore calls made through these function pointers |
michael@0 | 6 | var ignoreIndirectCalls = { |
michael@0 | 7 | "mallocSizeOf" : true, |
michael@0 | 8 | "aMallocSizeOf" : true, |
michael@0 | 9 | "_malloc_message" : true, |
michael@0 | 10 | "__conv" : true, |
michael@0 | 11 | "__convf" : true, |
michael@0 | 12 | "prerrortable.c:callback_newtable" : true, |
michael@0 | 13 | "mozalloc_oom.cpp:void (* gAbortHandler)(size_t)" : true, |
michael@0 | 14 | |
michael@0 | 15 | // I don't know why these are getting truncated |
michael@0 | 16 | "nsTraceRefcnt.cpp:void (* leakyLogAddRef)(void*": true, |
michael@0 | 17 | "nsTraceRefcnt.cpp:void (* leakyLogAddRef)(void*, int, int)": true, |
michael@0 | 18 | "nsTraceRefcnt.cpp:void (* leakyLogRelease)(void*": true, |
michael@0 | 19 | "nsTraceRefcnt.cpp:void (* leakyLogRelease)(void*, int, int)": true, |
michael@0 | 20 | }; |
michael@0 | 21 | |
michael@0 | 22 | function indirectCallCannotGC(fullCaller, fullVariable) |
michael@0 | 23 | { |
michael@0 | 24 | var caller = readable(fullCaller); |
michael@0 | 25 | |
michael@0 | 26 | // This is usually a simple variable name, but sometimes a full name gets |
michael@0 | 27 | // passed through. And sometimes that name is truncated. Examples: |
michael@0 | 28 | // _ZL13gAbortHandler|mozalloc_oom.cpp:void (* gAbortHandler)(size_t) |
michael@0 | 29 | // _ZL14pMutexUnlockFn|umutex.cpp:void (* pMutexUnlockFn)(const void* |
michael@0 | 30 | var name = readable(fullVariable); |
michael@0 | 31 | |
michael@0 | 32 | if (name in ignoreIndirectCalls) |
michael@0 | 33 | return true; |
michael@0 | 34 | |
michael@0 | 35 | if (name == "mapper" && caller == "ptio.c:pt_MapError") |
michael@0 | 36 | return true; |
michael@0 | 37 | |
michael@0 | 38 | if (name == "params" && caller == "PR_ExplodeTime") |
michael@0 | 39 | return true; |
michael@0 | 40 | |
michael@0 | 41 | if (name == "op" && /GetWeakmapKeyDelegate/.test(caller)) |
michael@0 | 42 | return true; |
michael@0 | 43 | |
michael@0 | 44 | var CheckCallArgs = "AsmJS.cpp:uint8 CheckCallArgs(FunctionCompiler*, js::frontend::ParseNode*, (uint8)(FunctionCompiler*,js::frontend::ParseNode*,Type)*, FunctionCompiler::Call*)"; |
michael@0 | 45 | if (name == "checkArg" && caller == CheckCallArgs) |
michael@0 | 46 | return true; |
michael@0 | 47 | |
michael@0 | 48 | // hook called during script finalization which cannot GC. |
michael@0 | 49 | if (/CallDestroyScriptHook/.test(caller)) |
michael@0 | 50 | return true; |
michael@0 | 51 | |
michael@0 | 52 | // template method called during marking and hence cannot GC |
michael@0 | 53 | if (name == "op" && caller.indexOf("bool js::WeakMap<Key, Value, HashPolicy>::keyNeedsMark(JSObject*)") != -1) |
michael@0 | 54 | { |
michael@0 | 55 | return true; |
michael@0 | 56 | } |
michael@0 | 57 | |
michael@0 | 58 | return false; |
michael@0 | 59 | } |
michael@0 | 60 | |
michael@0 | 61 | // Ignore calls through functions pointers with these types |
michael@0 | 62 | var ignoreClasses = { |
michael@0 | 63 | "JSTracer" : true, |
michael@0 | 64 | "JSStringFinalizer" : true, |
michael@0 | 65 | "SprintfState" : true, |
michael@0 | 66 | "SprintfStateStr" : true, |
michael@0 | 67 | "JSLocaleCallbacks" : true, |
michael@0 | 68 | "JSC::ExecutableAllocator" : true, |
michael@0 | 69 | "PRIOMethods": true, |
michael@0 | 70 | "XPCOMFunctions" : true, // I'm a little unsure of this one |
michael@0 | 71 | "_MD_IOVector" : true, |
michael@0 | 72 | }; |
michael@0 | 73 | |
michael@0 | 74 | // Ignore calls through TYPE.FIELD, where TYPE is the class or struct name containing |
michael@0 | 75 | // a function pointer field named FIELD. |
michael@0 | 76 | var ignoreCallees = { |
michael@0 | 77 | "js::Class.trace" : true, |
michael@0 | 78 | "js::Class.finalize" : true, |
michael@0 | 79 | "JSRuntime.destroyPrincipals" : true, |
michael@0 | 80 | "icu_50::UObject.__deleting_dtor" : true, // destructors in ICU code can't cause GC |
michael@0 | 81 | "mozilla::CycleCollectedJSRuntime.DescribeCustomObjects" : true, // During tracing, cannot GC. |
michael@0 | 82 | "mozilla::CycleCollectedJSRuntime.NoteCustomGCThingXPCOMChildren" : true, // During tracing, cannot GC. |
michael@0 | 83 | "PLDHashTableOps.hashKey" : true, |
michael@0 | 84 | "z_stream_s.zfree" : true, |
michael@0 | 85 | }; |
michael@0 | 86 | |
michael@0 | 87 | function fieldCallCannotGC(csu, fullfield) |
michael@0 | 88 | { |
michael@0 | 89 | if (csu in ignoreClasses) |
michael@0 | 90 | return true; |
michael@0 | 91 | if (fullfield in ignoreCallees) |
michael@0 | 92 | return true; |
michael@0 | 93 | return false; |
michael@0 | 94 | } |
michael@0 | 95 | |
michael@0 | 96 | function ignoreEdgeUse(edge, variable) |
michael@0 | 97 | { |
michael@0 | 98 | // Functions which should not be treated as using variable. |
michael@0 | 99 | if (edge.Kind == "Call") { |
michael@0 | 100 | var callee = edge.Exp[0]; |
michael@0 | 101 | if (callee.Kind == "Var") { |
michael@0 | 102 | var name = callee.Variable.Name[0]; |
michael@0 | 103 | if (/~Anchor/.test(name)) |
michael@0 | 104 | return true; |
michael@0 | 105 | if (/~DebugOnly/.test(name)) |
michael@0 | 106 | return true; |
michael@0 | 107 | if (/~ScopedThreadSafeStringInspector/.test(name)) |
michael@0 | 108 | return true; |
michael@0 | 109 | } |
michael@0 | 110 | } |
michael@0 | 111 | |
michael@0 | 112 | return false; |
michael@0 | 113 | } |
michael@0 | 114 | |
michael@0 | 115 | function ignoreEdgeAddressTaken(edge) |
michael@0 | 116 | { |
michael@0 | 117 | // Functions which may take indirect pointers to unrooted GC things, |
michael@0 | 118 | // but will copy them into rooted locations before calling anything |
michael@0 | 119 | // that can GC. These parameters should usually be replaced with |
michael@0 | 120 | // handles or mutable handles. |
michael@0 | 121 | if (edge.Kind == "Call") { |
michael@0 | 122 | var callee = edge.Exp[0]; |
michael@0 | 123 | if (callee.Kind == "Var") { |
michael@0 | 124 | var name = callee.Variable.Name[0]; |
michael@0 | 125 | if (/js::Invoke\(/.test(name)) |
michael@0 | 126 | return true; |
michael@0 | 127 | } |
michael@0 | 128 | } |
michael@0 | 129 | |
michael@0 | 130 | return false; |
michael@0 | 131 | } |
michael@0 | 132 | |
michael@0 | 133 | // Ignore calls of these functions (so ignore any stack containing these) |
michael@0 | 134 | var ignoreFunctions = { |
michael@0 | 135 | "ptio.c:pt_MapError" : true, |
michael@0 | 136 | "PR_ExplodeTime" : true, |
michael@0 | 137 | "PR_ErrorInstallTable" : true, |
michael@0 | 138 | "PR_SetThreadPrivate" : true, |
michael@0 | 139 | "JSObject* js::GetWeakmapKeyDelegate(JSObject*)" : true, // FIXME: mark with AutoAssertNoGC instead |
michael@0 | 140 | "uint8 NS_IsMainThread()" : true, |
michael@0 | 141 | |
michael@0 | 142 | // FIXME! |
michael@0 | 143 | "NS_LogInit": true, |
michael@0 | 144 | "NS_LogTerm": true, |
michael@0 | 145 | "NS_LogAddRef": true, |
michael@0 | 146 | "NS_LogRelease": true, |
michael@0 | 147 | "NS_LogCtor": true, |
michael@0 | 148 | "NS_LogDtor": true, |
michael@0 | 149 | "NS_LogCOMPtrAddRef": true, |
michael@0 | 150 | "NS_LogCOMPtrRelease": true, |
michael@0 | 151 | |
michael@0 | 152 | // FIXME! |
michael@0 | 153 | "NS_DebugBreak": true, |
michael@0 | 154 | |
michael@0 | 155 | // These are a little overzealous -- these destructors *can* GC if they end |
michael@0 | 156 | // up wrapping a pending exception. See bug 898815 for the heavyweight fix. |
michael@0 | 157 | "void js::AutoCompartment::~AutoCompartment(int32)" : true, |
michael@0 | 158 | "void JSAutoCompartment::~JSAutoCompartment(int32)" : true, |
michael@0 | 159 | |
michael@0 | 160 | // Bug 948646 - the only thing AutoJSContext's constructor calls |
michael@0 | 161 | // is an Init() routine whose entire body is covered with an |
michael@0 | 162 | // AutoAssertNoGC. AutoSafeJSContext is the same thing, just with |
michael@0 | 163 | // a different value for the 'aSafe' parameter. |
michael@0 | 164 | "void mozilla::AutoJSContext::AutoJSContext(mozilla::detail::GuardObjectNotifier*)" : true, |
michael@0 | 165 | "void mozilla::AutoSafeJSContext::~AutoSafeJSContext(int32)" : true, |
michael@0 | 166 | |
michael@0 | 167 | // And these are workarounds to avoid even more analysis work, |
michael@0 | 168 | // which would sadly still be needed even with bug 898815. |
michael@0 | 169 | "void js::AutoCompartment::AutoCompartment(js::ExclusiveContext*, JSCompartment*)": true, |
michael@0 | 170 | }; |
michael@0 | 171 | |
michael@0 | 172 | function ignoreGCFunction(mangled) |
michael@0 | 173 | { |
michael@0 | 174 | assert(mangled in readableNames); |
michael@0 | 175 | var fun = readableNames[mangled][0]; |
michael@0 | 176 | |
michael@0 | 177 | if (fun in ignoreFunctions) |
michael@0 | 178 | return true; |
michael@0 | 179 | |
michael@0 | 180 | // Templatized function |
michael@0 | 181 | if (fun.indexOf("void nsCOMPtr<T>::Assert_NoQueryNeeded()") >= 0) |
michael@0 | 182 | return true; |
michael@0 | 183 | |
michael@0 | 184 | // XXX modify refillFreeList<NoGC> to not need data flow analysis to understand it cannot GC. |
michael@0 | 185 | if (/refillFreeList/.test(fun) && /\(js::AllowGC\)0u/.test(fun)) |
michael@0 | 186 | return true; |
michael@0 | 187 | return false; |
michael@0 | 188 | } |
michael@0 | 189 | |
michael@0 | 190 | function isRootedTypeName(name) |
michael@0 | 191 | { |
michael@0 | 192 | if (name == "mozilla::ErrorResult" || |
michael@0 | 193 | name == "JSErrorResult" || |
michael@0 | 194 | name == "WrappableJSErrorResult" || |
michael@0 | 195 | name == "js::frontend::TokenStream" || |
michael@0 | 196 | name == "js::frontend::TokenStream::Position" || |
michael@0 | 197 | name == "ModuleCompiler") |
michael@0 | 198 | { |
michael@0 | 199 | return true; |
michael@0 | 200 | } |
michael@0 | 201 | return false; |
michael@0 | 202 | } |
michael@0 | 203 | |
michael@0 | 204 | function isRootedPointerTypeName(name) |
michael@0 | 205 | { |
michael@0 | 206 | if (name.startsWith('struct ')) |
michael@0 | 207 | name = name.substr(7); |
michael@0 | 208 | if (name.startsWith('class ')) |
michael@0 | 209 | name = name.substr(6); |
michael@0 | 210 | if (name.startsWith('const ')) |
michael@0 | 211 | name = name.substr(6); |
michael@0 | 212 | if (name.startsWith('js::ctypes::')) |
michael@0 | 213 | name = name.substr(12); |
michael@0 | 214 | if (name.startsWith('js::')) |
michael@0 | 215 | name = name.substr(4); |
michael@0 | 216 | if (name.startsWith('JS::')) |
michael@0 | 217 | name = name.substr(4); |
michael@0 | 218 | if (name.startsWith('mozilla::dom::')) |
michael@0 | 219 | name = name.substr(14); |
michael@0 | 220 | |
michael@0 | 221 | if (name.startsWith('MaybeRooted<')) |
michael@0 | 222 | return /\(js::AllowGC\)1u>::RootType/.test(name); |
michael@0 | 223 | |
michael@0 | 224 | return name.startsWith('Rooted') || name.startsWith('PersistentRooted'); |
michael@0 | 225 | } |
michael@0 | 226 | |
michael@0 | 227 | function isSuppressConstructor(name) |
michael@0 | 228 | { |
michael@0 | 229 | return name.indexOf("::AutoSuppressGC") != -1 |
michael@0 | 230 | || name.indexOf("::AutoEnterAnalysis") != -1 |
michael@0 | 231 | || name.indexOf("::AutoAssertNoGC") != -1 |
michael@0 | 232 | || name.indexOf("::AutoIgnoreRootingHazards") != -1; |
michael@0 | 233 | } |
michael@0 | 234 | |
michael@0 | 235 | // nsISupports subclasses' methods may be scriptable (or overridden |
michael@0 | 236 | // via binary XPCOM), and so may GC. But some fields just aren't going |
michael@0 | 237 | // to get overridden with something that can GC. |
michael@0 | 238 | function isOverridableField(initialCSU, csu, field) |
michael@0 | 239 | { |
michael@0 | 240 | if (csu != 'nsISupports') |
michael@0 | 241 | return false; |
michael@0 | 242 | if (field == 'GetCurrentJSContext') |
michael@0 | 243 | return false; |
michael@0 | 244 | if (field == 'IsOnCurrentThread') |
michael@0 | 245 | return false; |
michael@0 | 246 | if (field == 'GetNativeContext') |
michael@0 | 247 | return false; |
michael@0 | 248 | if (field == "GetGlobalJSObject") |
michael@0 | 249 | return false; |
michael@0 | 250 | if (field == "GetIsMainThread") |
michael@0 | 251 | return false; |
michael@0 | 252 | if (initialCSU == 'nsIXPConnectJSObjectHolder' && field == 'GetJSObject') |
michael@0 | 253 | return false; |
michael@0 | 254 | |
michael@0 | 255 | return true; |
michael@0 | 256 | } |