Closed Bug 765218 (CVE-2012-1953) Opened 12 years ago Closed 12 years ago

Out of bounds read in ElementAnimations::EnsureStyleRuleFor

Categories

(Core :: CSS Parsing and Computation, defect)

defect
Not set
critical

Tracking

()

VERIFIED FIXED
mozilla16
Tracking Status
firefox14 + fixed
firefox15 + verified
firefox16 + verified
firefox-esr10 14+ fixed

People

(Reporter: inferno, Assigned: dbaron)

References

Details

(Keywords: crash, regression, sec-moderate, Whiteboard: [asan][advisory-tracking+][qa-])

Attachments

(2 files)

Attached file Testcase
Reproduces on trunk ================================================================= ==32187== ERROR: AddressSanitizer heap-buffer-overflow on address 0x7f9aecc43f3c at pc 0x7f9b1682427b bp 0x7fffc335c370 sp 0x7fffc335c368 READ of size 4 at 0x7f9aecc43f3c thread T0 #0 0x7f9b1682427b in ElementAnimations::EnsureStyleRuleFor(mozilla::TimeStamp, InfallibleTArray<nsAnimationManager::AnimationEventInfo>&) firefox/src/layout/style/nsAnimationManager.cpp:274 #1 0x7f9b1682a9f9 in nsAnimationManager::CheckAnimationRule(nsStyleContext*, mozilla::dom::Element*) firefox/src/layout/style/nsAnimationManager.cpp:518 #2 0x7f9b16d378d3 in nsStyleSet::GetContext(nsStyleContext*, nsRuleNode*, nsRuleNode*, bool, bool, nsIAtom*, nsCSSPseudoElements::Type, bool, mozilla::dom::Element*) firefox/src/layout/style/nsStyleSet.cpp:618 #3 0x7f9b16d3f06d in nsStyleSet::ResolveStyleFor(mozilla::dom::Element*, nsStyleContext*, TreeMatchContext&) firefox/src/layout/style/nsStyleSet.cpp:953 #4 0x7f9b15aa8e90 in nsCSSFrameConstructor::ResolveStyleContext(nsStyleContext*, nsIContent*, nsFrameConstructorState*) firefox/src/layout/base/nsCSSFrameConstructor.cpp:4546 #5 0x7f9b15aa88ea in nsCSSFrameConstructor::ResolveStyleContext(nsIFrame*, nsIContent*, nsFrameConstructorState*) firefox/src/layout/base/nsCSSFrameConstructor.cpp:4533 #6 0x7f9b15aaea7b in nsCSSFrameConstructor::AddFrameConstructionItems(nsFrameConstructorState&, nsIContent*, bool, nsIFrame*, nsCSSFrameConstructor::FrameConstructionItemList&) firefox/src/layout/base/nsCSSFrameConstructor.cpp:4986 #7 0x7f9b15ad1c98 in nsCSSFrameConstructor::ContentAppended(nsIContent*, nsIContent*, bool) firefox/src/layout/base/nsCSSFrameConstructor.cpp:6552 #8 0x7f9b15ac930f in nsCSSFrameConstructor::CreateNeededFrames(nsIContent*) firefox/src/layout/base/nsCSSFrameConstructor.cpp:6244 #9 0x7f9b15ac9435 in nsCSSFrameConstructor::CreateNeededFrames(nsIContent*) firefox/src/layout/base/nsCSSFrameConstructor.cpp:6256 #10 0x7f9b15ad3a1b in nsCSSFrameConstructor::CreateNeededFrames() firefox/src/layout/base/nsCSSFrameConstructor.cpp:6270 #11 0x7f9b15ee3fab in PresShell::FlushPendingNotifications(mozFlushType) firefox/src/layout/base/nsPresShell.cpp:3813 #12 0x7f9b177360fe in nsDocument::FlushPendingNotifications(mozFlushType) firefox/src/content/base/src/nsDocument.cpp:6297 #13 0x7f9b1d6052a4 in nsDocLoader::DocLoaderIsEmpty(bool) firefox/src/uriloader/base/nsDocLoader.cpp:775 #14 0x7f9b1d609c1c in nsDocLoader::OnStopRequest(nsIRequest*, nsISupports*, unsigned int) firefox/src/uriloader/base/nsDocLoader.cpp:704 #15 0x7f9b1d60b76d in non-virtual thunk to nsDocLoader::OnStopRequest(nsIRequest*, nsISupports*, unsigned int) firefox/src/modules/zlib/src/inffast.c:0 #16 0x7f9b146f7669 in nsLoadGroup::RemoveRequest(nsIRequest*, nsISupports*, unsigned int) firefox/src/netwerk/base/src/nsLoadGroup.cpp:698 #17 0x7f9b1774a9a4 in nsDocument::DoUnblockOnload() firefox/src/content/base/src/nsDocument.cpp:7166 #18 0x7f9b1774a431 in nsDocument::UnblockOnload(bool) firefox/src/content/base/src/nsDocument.cpp:7109 #19 0x7f9b176fc967 in nsDocument::DispatchContentLoadedEvents() firefox/src/content/base/src/nsDocument.cpp:4180 #20 0x7f9b177bbe49 in nsRunnableMethodImpl<void (nsDocument::*)(), true>::Run() firefox/src/../../../dist/include/nsThreadUtils.h:349 #21 0x7f9b20b38463 in nsThread::ProcessNextEvent(bool, bool*) firefox/src/xpcom/threads/nsThread.cpp:625 #22 0x7f9b207c7a0d in NS_ProcessNextEvent_P(nsIThread*, bool) firefox/src/objdir-ff-asan-sym/xpcom/build/nsThreadUtils.cpp:216 #23 0x7f9b1d9ba5a6 in nsXULWindow::ShowModal() firefox/src/xpfe/appshell/src/nsXULWindow.cpp:378 #24 0x7f9b1d99d522 in nsContentTreeOwner::ShowAsModal() firefox/src/xpfe/appshell/src/nsContentTreeOwner.cpp:529 #25 0x7f9b1d99d69c in non-virtual thunk to nsContentTreeOwner::ShowAsModal() firefox/src/modules/zlib/src/inffast.c:0 #26 0x7f9b1d7c5844 in nsWindowWatcher::OpenWindowJSInternal(nsIDOMWindow*, char const*, char const*, char const*, bool, nsIArray*, bool, nsIDOMWindow**) firefox/src/embedding/components/windowwatcher/src/nsWindowWatcher.cpp:1000 #27 0x7f9b1d7bbe21 in nsWindowWatcher::OpenWindow(nsIDOMWindow*, char const*, char const*, char const*, nsISupports*, nsIDOMWindow**) firefox/src/embedding/components/windowwatcher/src/nsWindowWatcher.cpp:381 #28 0x7f9b20c36dea in NS_InvokeByIndex_P firefox/src/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_x86_64_unix.cpp:161 #29 0x7f9b1c5c3b87 in CallMethodHelper::Invoke() firefox/src/js/xpconnect/src/XPCWrappedNative.cpp:3107 #30 0x7f9b1c62beef in XPC_WN_CallMethod(JSContext*, unsigned int, JS::Value*) firefox/src/js/xpconnect/src/XPCWrappedNativeJSOps.cpp:1500 #31 0x7f9b25e1c23d in js::CallJSNative(JSContext*, int (*)(JSContext*, unsigned int, JS::Value*), js::CallArgs const&) firefox/src/js/src/jscntxtinlines.h:395 #32 0x7f9b25d8ff1b in js::Interpret(JSContext*, js::StackFrame*, js::InterpMode) firefox/src/js/src/jsinterp.cpp:2435 #33 0x7f9b25d15317 in js::RunScript(JSContext*, JSScript*, js::StackFrame*) firefox/src/js/src/jsinterp.cpp:267 #34 0x7f9b25e1c65f in js::InvokeKernel(JSContext*, js::CallArgs, js::MaybeConstruct) firefox/src/js/src/jsinterp.cpp:322 #35 0x7f9b257d8090 in js::Invoke(JSContext*, js::InvokeArgsGuard&, js::MaybeConstruct) firefox/src/js/src/jsinterp.h:100 #36 0x7f9b25e2178d in js::Invoke(JSContext*, JS::Value const&, JS::Value const&, unsigned int, JS::Value*, JS::Value*) firefox/src/js/src/jsinterp.cpp:354 #37 0x7f9b25682459 in JS_CallFunctionValue firefox/src/js/src/jsapi.cpp:5490 #38 0x7f9b1c571f81 in nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS*, unsigned short, XPTMethodDescriptor const*, nsXPTCMiniVariant*) firefox/src/js/xpconnect/src/XPCWrappedJSClass.cpp:1475 #39 0x7f9b1c523198 in nsXPCWrappedJS::CallMethod(unsigned short, XPTMethodDescriptor const*, nsXPTCMiniVariant*) firefox/src/js/xpconnect/src/XPCWrappedJS.cpp:579 #40 0x7f9b20c3c9a0 in PrepareAndDispatch firefox/src/xpcom/reflect/xptcall/src/md/unix/xptcstubs_x86_64_linux.cpp:121 #41 0x7f9b20c3a137 in SharedStub firefox/src/xpcom/reflect/xptcall/src/md/unix/xptcstubs_x86_64_linux.cpp:0 #42 0x7f9b20c36dea in NS_InvokeByIndex_P firefox/src/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_x86_64_unix.cpp:161 #43 0x7f9b1c5c3b87 in CallMethodHelper::Invoke() firefox/src/js/xpconnect/src/XPCWrappedNative.cpp:3107 #44 0x7f9b1c62beef in XPC_WN_CallMethod(JSContext*, unsigned int, JS::Value*) firefox/src/js/xpconnect/src/XPCWrappedNativeJSOps.cpp:1500 #45 0x7f9b25e1c23d in js::CallJSNative(JSContext*, int (*)(JSContext*, unsigned int, JS::Value*), js::CallArgs const&) firefox/src/js/src/jscntxtinlines.h:395 #46 0x7f9b25d8ff1b in js::Interpret(JSContext*, js::StackFrame*, js::InterpMode) firefox/src/js/src/jsinterp.cpp:2435 #47 0x7f9b25d15317 in js::RunScript(JSContext*, JSScript*, js::StackFrame*) firefox/src/js/src/jsinterp.cpp:267 #48 0x7f9b25e1c65f in js::InvokeKernel(JSContext*, js::CallArgs, js::MaybeConstruct) firefox/src/js/src/jsinterp.cpp:322 #49 0x7f9b257d8090 in js::Invoke(JSContext*, js::InvokeArgsGuard&, js::MaybeConstruct) firefox/src/js/src/jsinterp.h:100 #50 0x7f9b25ad94f4 in js::CallOrConstructBoundFunction(JSContext*, unsigned int, JS::Value*) firefox/src/js/src/jsfun.cpp:862 #51 0x7f9b25e1c23d in js::CallJSNative(JSContext*, int (*)(JSContext*, unsigned int, JS::Value*), js::CallArgs const&) firefox/src/js/src/jscntxtinlines.h:395 #52 0x7f9b257d8090 in js::Invoke(JSContext*, js::InvokeArgsGuard&, js::MaybeConstruct) firefox/src/js/src/jsinterp.h:100 #53 0x7f9b25e2178d in js::Invoke(JSContext*, JS::Value const&, JS::Value const&, unsigned int, JS::Value*, JS::Value*) firefox/src/js/src/jsinterp.cpp:354 #54 0x7f9b25682459 in JS_CallFunctionValue firefox/src/js/src/jsapi.cpp:5490 #55 0x7f9b1c571f81 in nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS*, unsigned short, XPTMethodDescriptor const*, nsXPTCMiniVariant*) firefox/src/js/xpconnect/src/XPCWrappedJSClass.cpp:1475 #56 0x7f9b1c523198 in nsXPCWrappedJS::CallMethod(unsigned short, XPTMethodDescriptor const*, nsXPTCMiniVariant*) firefox/src/js/xpconnect/src/XPCWrappedJS.cpp:579 #57 0x7f9b20c3c9a0 in PrepareAndDispatch firefox/src/xpcom/reflect/xptcall/src/md/unix/xptcstubs_x86_64_linux.cpp:121 #58 0x7f9b20c3a137 in SharedStub firefox/src/xpcom/reflect/xptcall/src/md/unix/xptcstubs_x86_64_linux.cpp:0 #59 0x7f9b20b38463 in nsThread::ProcessNextEvent(bool, bool*) firefox/src/xpcom/threads/nsThread.cpp:625 #60 0x7f9b207c7a0d in NS_ProcessNextEvent_P(nsIThread*, bool) firefox/src/objdir-ff-asan-sym/xpcom/build/nsThreadUtils.cpp:216 #61 0x7f9b1f92b626 in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) firefox/src/ipc/glue/MessagePump.cpp:82 #62 0x7f9b20de848a in MessageLoop::RunInternal() firefox/src/ipc/chromium/src/base/message_loop.cc:209 #63 0x7f9b20de82d3 in MessageLoop::RunHandler() firefox/src/ipc/chromium/src/base/message_loop.cc:202 0x7f9aecc43f3c is located 4 bytes to the right of 184-byte region [0x7f9aecc43e80,0x7f9aecc43f38) allocated by thread T0 here: #0 0x4a33e2 in malloc ??:0 #1 0x7f9b2d36b737 in moz_xmalloc firefox/src/memory/mozalloc/mozalloc.cpp:54 #2 0x7f9b146d7483 in nsTArrayInfallibleAllocator::Malloc(unsigned long) firefox/src/../../dist/include/nsTArray.h:56 #3 0x7f9b154e96d8 in nsTArray_base<nsTArrayInfallibleAllocator>::EnsureCapacity(unsigned int, unsigned int) firefox/src/../../dist/include/nsTArray-inl.h:119 #4 0x7f9b16840a4d in nsTArray<AnimationPropertySegment, nsTArrayInfallibleAllocator>::AppendElements(unsigned int) firefox/src/../../dist/include/nsTArray.h:891 #5 0x7f9b16835ff8 in nsTArray<AnimationPropertySegment, nsTArrayInfallibleAllocator>::AppendElement() firefox/src/../../dist/include/nsTArray.h:906 #6 0x7f9b16834e62 in nsAnimationManager::BuildSegment(InfallibleTArray<AnimationPropertySegment>&, nsCSSProperty, nsAnimation const&, float, nsStyleContext*, mozilla::css::Declaration*, float, nsStyleContext*) firefox/src/layout/style/nsAnimationManager.cpp:805 #7 0x7f9b1682ea72 in nsAnimationManager::BuildAnimations(nsStyleContext*, InfallibleTArray<ElementAnimation>&) firefox/src/layout/style/nsAnimationManager.cpp:746 #8 0x7f9b16829a02 in nsAnimationManager::CheckAnimationRule(nsStyleContext*, mozilla::dom::Element*) firefox/src/layout/style/nsAnimationManager.cpp:442 #9 0x7f9b16d378d3 in nsStyleSet::GetContext(nsStyleContext*, nsRuleNode*, nsRuleNode*, bool, bool, nsIAtom*, nsCSSPseudoElements::Type, bool, mozilla::dom::Element*) firefox/src/layout/style/nsStyleSet.cpp:618 #10 0x7f9b16d3f06d in nsStyleSet::ResolveStyleFor(mozilla::dom::Element*, nsStyleContext*, TreeMatchContext&) firefox/src/layout/style/nsStyleSet.cpp:953 #11 0x7f9b15aa8e90 in nsCSSFrameConstructor::ResolveStyleContext(nsStyleContext*, nsIContent*, nsFrameConstructorState*) firefox/src/layout/base/nsCSSFrameConstructor.cpp:4546 #12 0x7f9b15aa88ea in nsCSSFrameConstructor::ResolveStyleContext(nsIFrame*, nsIContent*, nsFrameConstructorState*) firefox/src/layout/base/nsCSSFrameConstructor.cpp:4533 #13 0x7f9b15aaea7b in nsCSSFrameConstructor::AddFrameConstructionItems(nsFrameConstructorState&, nsIContent*, bool, nsIFrame*, nsCSSFrameConstructor::FrameConstructionItemList&) firefox/src/layout/base/nsCSSFrameConstructor.cpp:4986 #14 0x7f9b15ad1c98 in nsCSSFrameConstructor::ContentAppended(nsIContent*, nsIContent*, bool) firefox/src/layout/base/nsCSSFrameConstructor.cpp:6552 #15 0x7f9b15ac930f in nsCSSFrameConstructor::CreateNeededFrames(nsIContent*) firefox/src/layout/base/nsCSSFrameConstructor.cpp:6244 #16 0x7f9b15ac9435 in nsCSSFrameConstructor::CreateNeededFrames(nsIContent*) firefox/src/layout/base/nsCSSFrameConstructor.cpp:6256 #17 0x7f9b15ad3a1b in nsCSSFrameConstructor::CreateNeededFrames() firefox/src/layout/base/nsCSSFrameConstructor.cpp:6270 #18 0x7f9b15ee3fab in PresShell::FlushPendingNotifications(mozFlushType) firefox/src/layout/base/nsPresShell.cpp:3813 #19 0x7f9b177360fe in nsDocument::FlushPendingNotifications(mozFlushType) firefox/src/content/base/src/nsDocument.cpp:6297 #20 0x7f9b1d6052a4 in nsDocLoader::DocLoaderIsEmpty(bool) firefox/src/uriloader/base/nsDocLoader.cpp:775 #21 0x7f9b1d609c1c in nsDocLoader::OnStopRequest(nsIRequest*, nsISupports*, unsigned int) firefox/src/uriloader/base/nsDocLoader.cpp:704 #22 0x7f9b1d60b76d in non-virtual thunk to nsDocLoader::OnStopRequest(nsIRequest*, nsISupports*, unsigned int) firefox/src/modules/zlib/src/inffast.c:0 ==32187== ABORTING Stats: 148M malloced (160M for red zones) by 338879 calls Stats: 44M realloced by 18848 calls Stats: 111M freed by 216201 calls Stats: 0M really freed by 0 calls Stats: 340M (87089 full pages) mmaped in 85 calls mmaps by size class: 8:262128; 9:49146; 10:20475; 11:18423; 12:3072; 13:2048; 14:1536; 15:384; 16:512; 17:128; 18:160; 19:56; 20:16; mallocs by size class: 8:254257; 9:45545; 10:15976; 11:16377; 12:2361; 13:1796; 14:1413; 15:319; 16:512; 17:111; 18:149; 19:49; 20:14; frees by size class: 8:150107; 9:35624; 10:12657; 11:13226; 12:1528; 13:913; 14:1224; 15:268; 16:443; 17:97; 18:57; 19:46; 20:11; rfrees by size class: Stats: malloc large: 323 small slow: 1782 Shadow byte and word: 0x1ff35d9887e7: fb 0x1ff35d9887e0: 00 00 00 00 00 00 00 fb More shadow bytes: 0x1ff35d9887c0: fa fa fa fa fa fa fa fa 0x1ff35d9887c8: fa fa fa fa fa fa fa fa 0x1ff35d9887d0: 00 00 00 00 00 00 00 00 0x1ff35d9887d8: 00 00 00 00 00 00 00 00 =>0x1ff35d9887e0: 00 00 00 00 00 00 00 fb 0x1ff35d9887e8: fb fb fb fb fb fb fb fb 0x1ff35d9887f0: fa fa fa fa fa fa fa fa 0x1ff35d9887f8: fa fa fa fa fa fa fa fa 0x1ff35d988800: fa fa fa fa fa fa fa fa
Severity: normal → critical
Component: General → Style System (CSS)
Keywords: crash
Product: Firefox → Core
QA Contact: general → style-system
Whiteboard: [asan]
I think part of what went wrong is that when I wrote this code: if (whichIteration == anim.mIterationCount) { // When the animation's iteration count is an integer (as it // normally is), we need to end at 100% of its last iteration // rather than 0% of the next one. --whichIteration; } I wasn't considering the possibility that whichIteration (and anim.mIterationCount) were 0. (I need to compare to the way currentIterationCount is calculated.)
Attached patch patchSplinter Review
Attachment #634599 - Flags: review?(bzbarsky)
So without this patch, what happened was that whichIteration would end up being PRUint32(-1) which is really PRUint32(2^31 - 1), which mean that positionInIteration would end up being double(2^32) (because of 'alternate'), and then we'd either fail (in a debug build): NS_ABORT_IF_FALSE(0.0 <= positionInIteration && positionInIteration <= 1.0, "position should be in [0-1]"); or we'd end up reading off the end of the segments array a bit below. So then we'd end up reading data off the end of an array: doing floating point math on it, and potentially dereferencing pointers (if the tags in the nsStyleAnimation::Value are right for that). I'm not sure what security rating that deserves.
Flags: in-testsuite?
Depends on what they point at. If they're objects with virtual methods and we call anything on it then that's very bad. Depends on what we're doing with them.
They're tagged union objects without virtual methods, though if you have the right tag *twice* (i.e., a tagged union pointed to by another tagged union) you could get to an object with virtual methods on the fourth dereference (nsStyleAnimation::Value* -> nsCSSValue* -> nsCSSValue::Image* -> imgIRequest*). Maybe even the third if I'm missing a shorter path.
Attachment #634599 - Flags: review?(bzbarsky) → review+
Assignee: nobody → dbaron
Hardware: x86_64 → All
Target Milestone: --- → mozilla16
Comment on attachment 634599 [details] [diff] [review] patch [Approval Request Comment] Bug caused by (feature/regressing bug #): bug 435442 User impact if declined: Crash, potentially exploitable with difficulty Testing completed (on m-c, etc.): on mozilla-inbound Risk to taking this patch (and alternatives if risky): Very low risk; changes the behavior only when -moz-animation-iteration-count is 0, which is a basically-useless value String or UUID changes made by this patch: none
Attachment #634599 - Flags: approval-mozilla-beta?
Attachment #634599 - Flags: approval-mozilla-aurora?
Status: NEW → RESOLVED
Closed: 12 years ago
Resolution: --- → FIXED
Attachment #634599 - Flags: approval-mozilla-esr10?
Comment on attachment 634599 [details] [diff] [review] patch [Triage comment] approving for all branches, low risk and still early enough in the beta cycle that we should catch any issues.
Attachment #634599 - Flags: approval-mozilla-esr10?
Attachment #634599 - Flags: approval-mozilla-esr10+
Attachment #634599 - Flags: approval-mozilla-beta?
Attachment #634599 - Flags: approval-mozilla-beta+
Attachment #634599 - Flags: approval-mozilla-aurora?
Attachment #634599 - Flags: approval-mozilla-aurora+
Verified fixed with Firefox 16.0a1 Nightly 2012-07-10 and Firefox 15.0a2 Aurora 2012-07-10 ASAN builds. This bug cannot be verified fixed for Beta or ESR since we don't have ASAN builds for these branches.
Status: RESOLVED → VERIFIED
Whiteboard: [asan] → [asan][advisory-tracking+]
Marking qa- since we don't have Beta/ESR builds to verify against.
Whiteboard: [asan][advisory-tracking+] → [asan][advisory-tracking+][qa-]
Alias: CVE-2012-1953
Summary: Heap-buffer-overflow in ElementAnimations::EnsureStyleRuleFor → Out of bounds read in ElementAnimations::EnsureStyleRuleFor
Group: core-security
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: