Closed Bug 1603298 Opened 4 years ago Closed 2 years ago

call to function NS_NewGridContainerFrame through pointer to incorrect function type src/layout/base/nsCSSFrameConstructor.cpp:3568

Categories

(Core :: Layout, defect, P3)

defect

Tracking

()

RESOLVED FIXED
97 Branch
Tracking Status
firefox-esr91 --- wontfix
firefox73 --- wontfix
firefox95 --- wontfix
firefox96 --- wontfix
firefox97 --- fixed

People

(Reporter: tsmith, Assigned: emilio)

References

(Blocks 1 open bug)

Details

Attachments

(2 files, 1 obsolete file)

Found with m-c 20191211-b823b005f00e
This is triggered on start up with an UBSan build. To enable this check add the following to your mozconfig:

ac_add_options --enable-undefined-sanitizer="function"
src/layout/base/nsCSSFrameConstructor.cpp:3568:16: runtime error: call to function NS_NewGridContainerFrame(mozilla::PresShell*, mozilla::ComputedStyle*) through pointer to incorrect function type 'nsIFrame *(*)(mozilla::PresShell *, mozilla::ComputedStyle *)'
src/layout/generic/nsGridContainerFrame.cpp:3592: note: NS_NewGridContainerFrame(mozilla::PresShell*, mozilla::ComputedStyle*) defined here
    #0 0x7f14062c62dd in nsCSSFrameConstructor::ConstructFrameFromItemInternal(nsCSSFrameConstructor::FrameConstructionItem&, nsFrameConstructorState&, nsContainerFrame*, nsFrameList&) src/layout/base/nsCSSFrameConstructor.cpp:3568:16
    #1 0x7f14062ca831 in nsCSSFrameConstructor::ConstructFramesFromItem(nsFrameConstructorState&, nsCSSFrameConstructor::FrameConstructionItemList::Iterator&, nsContainerFrame*, nsFrameList&) src/layout/base/nsCSSFrameConstructor.cpp:5637:3
    #2 0x7f1406346ca5 in nsCSSFrameConstructor::ConstructFramesFromItemList(nsFrameConstructorState&, nsCSSFrameConstructor::FrameConstructionItemList&, nsContainerFrame*, bool, nsFrameList&) src/layout/base/nsCSSFrameConstructor.cpp:9496:5
    #3 0x7f14062b9f57 in nsCSSFrameConstructor::ProcessChildren(nsFrameConstructorState&, nsIContent*, mozilla::ComputedStyle*, nsContainerFrame*, bool, nsFrameList&, bool, nsIFrame*) src/layout/base/nsCSSFrameConstructor.cpp:9661:3
    #4 0x7f14062c5be9 in nsCSSFrameConstructor::ConstructFrameFromItemInternal(nsCSSFrameConstructor::FrameConstructionItem&, nsFrameConstructorState&, nsContainerFrame*, nsFrameList&) src/layout/base/nsCSSFrameConstructor.cpp:3714:9
    #5 0x7f14062ca831 in nsCSSFrameConstructor::ConstructFramesFromItem(nsFrameConstructorState&, nsCSSFrameConstructor::FrameConstructionItemList::Iterator&, nsContainerFrame*, nsFrameList&) src/layout/base/nsCSSFrameConstructor.cpp:5637:3
    #6 0x7f1406346ca5 in nsCSSFrameConstructor::ConstructFramesFromItemList(nsFrameConstructorState&, nsCSSFrameConstructor::FrameConstructionItemList&, nsContainerFrame*, bool, nsFrameList&) src/layout/base/nsCSSFrameConstructor.cpp:9496:5
    #7 0x7f14062b9f57 in nsCSSFrameConstructor::ProcessChildren(nsFrameConstructorState&, nsIContent*, mozilla::ComputedStyle*, nsContainerFrame*, bool, nsFrameList&, bool, nsIFrame*) src/layout/base/nsCSSFrameConstructor.cpp:9661:3
    #8 0x7f14062c5be9 in nsCSSFrameConstructor::ConstructFrameFromItemInternal(nsCSSFrameConstructor::FrameConstructionItem&, nsFrameConstructorState&, nsContainerFrame*, nsFrameList&) src/layout/base/nsCSSFrameConstructor.cpp:3714:9
    #9 0x7f14062ca831 in nsCSSFrameConstructor::ConstructFramesFromItem(nsFrameConstructorState&, nsCSSFrameConstructor::FrameConstructionItemList::Iterator&, nsContainerFrame*, nsFrameList&) src/layout/base/nsCSSFrameConstructor.cpp:5637:3
    #10 0x7f1406346ca5 in nsCSSFrameConstructor::ConstructFramesFromItemList(nsFrameConstructorState&, nsCSSFrameConstructor::FrameConstructionItemList&, nsContainerFrame*, bool, nsFrameList&) src/layout/base/nsCSSFrameConstructor.cpp:9496:5
    #11 0x7f14062b9f57 in nsCSSFrameConstructor::ProcessChildren(nsFrameConstructorState&, nsIContent*, mozilla::ComputedStyle*, nsContainerFrame*, bool, nsFrameList&, bool, nsIFrame*) src/layout/base/nsCSSFrameConstructor.cpp:9661:3
    #12 0x7f14062c5be9 in nsCSSFrameConstructor::ConstructFrameFromItemInternal(nsCSSFrameConstructor::FrameConstructionItem&, nsFrameConstructorState&, nsContainerFrame*, nsFrameList&) src/layout/base/nsCSSFrameConstructor.cpp:3714:9
    #13 0x7f14062ca831 in nsCSSFrameConstructor::ConstructFramesFromItem(nsFrameConstructorState&, nsCSSFrameConstructor::FrameConstructionItemList::Iterator&, nsContainerFrame*, nsFrameList&) src/layout/base/nsCSSFrameConstructor.cpp:5637:3
    #14 0x7f1406346ca5 in nsCSSFrameConstructor::ConstructFramesFromItemList(nsFrameConstructorState&, nsCSSFrameConstructor::FrameConstructionItemList&, nsContainerFrame*, bool, nsFrameList&) src/layout/base/nsCSSFrameConstructor.cpp:9496:5
    #15 0x7f14062b9f57 in nsCSSFrameConstructor::ProcessChildren(nsFrameConstructorState&, nsIContent*, mozilla::ComputedStyle*, nsContainerFrame*, bool, nsFrameList&, bool, nsIFrame*) src/layout/base/nsCSSFrameConstructor.cpp:9661:3
    #16 0x7f14062c5be9 in nsCSSFrameConstructor::ConstructFrameFromItemInternal(nsCSSFrameConstructor::FrameConstructionItem&, nsFrameConstructorState&, nsContainerFrame*, nsFrameList&) src/layout/base/nsCSSFrameConstructor.cpp:3714:9
    #17 0x7f14062ca831 in nsCSSFrameConstructor::ConstructFramesFromItem(nsFrameConstructorState&, nsCSSFrameConstructor::FrameConstructionItemList::Iterator&, nsContainerFrame*, nsFrameList&) src/layout/base/nsCSSFrameConstructor.cpp:5637:3
    #18 0x7f1406346ca5 in nsCSSFrameConstructor::ConstructFramesFromItemList(nsFrameConstructorState&, nsCSSFrameConstructor::FrameConstructionItemList&, nsContainerFrame*, bool, nsFrameList&) src/layout/base/nsCSSFrameConstructor.cpp:9496:5
    #19 0x7f14062b9f57 in nsCSSFrameConstructor::ProcessChildren(nsFrameConstructorState&, nsIContent*, mozilla::ComputedStyle*, nsContainerFrame*, bool, nsFrameList&, bool, nsIFrame*) src/layout/base/nsCSSFrameConstructor.cpp:9661:3
    #20 0x7f14062c5be9 in nsCSSFrameConstructor::ConstructFrameFromItemInternal(nsCSSFrameConstructor::FrameConstructionItem&, nsFrameConstructorState&, nsContainerFrame*, nsFrameList&) src/layout/base/nsCSSFrameConstructor.cpp:3714:9
    #21 0x7f14062ca831 in nsCSSFrameConstructor::ConstructFramesFromItem(nsFrameConstructorState&, nsCSSFrameConstructor::FrameConstructionItemList::Iterator&, nsContainerFrame*, nsFrameList&) src/layout/base/nsCSSFrameConstructor.cpp:5637:3
    #22 0x7f1406346ca5 in nsCSSFrameConstructor::ConstructFramesFromItemList(nsFrameConstructorState&, nsCSSFrameConstructor::FrameConstructionItemList&, nsContainerFrame*, bool, nsFrameList&) src/layout/base/nsCSSFrameConstructor.cpp:9496:5
    #23 0x7f14062b9f57 in nsCSSFrameConstructor::ProcessChildren(nsFrameConstructorState&, nsIContent*, mozilla::ComputedStyle*, nsContainerFrame*, bool, nsFrameList&, bool, nsIFrame*) src/layout/base/nsCSSFrameConstructor.cpp:9661:3
    #24 0x7f14062c5be9 in nsCSSFrameConstructor::ConstructFrameFromItemInternal(nsCSSFrameConstructor::FrameConstructionItem&, nsFrameConstructorState&, nsContainerFrame*, nsFrameList&) src/layout/base/nsCSSFrameConstructor.cpp:3714:9
    #25 0x7f14062ca831 in nsCSSFrameConstructor::ConstructFramesFromItem(nsFrameConstructorState&, nsCSSFrameConstructor::FrameConstructionItemList::Iterator&, nsContainerFrame*, nsFrameList&) src/layout/base/nsCSSFrameConstructor.cpp:5637:3
    #26 0x7f1406346ca5 in nsCSSFrameConstructor::ConstructFramesFromItemList(nsFrameConstructorState&, nsCSSFrameConstructor::FrameConstructionItemList&, nsContainerFrame*, bool, nsFrameList&) src/layout/base/nsCSSFrameConstructor.cpp:9496:5
    #27 0x7f14062b9f57 in nsCSSFrameConstructor::ProcessChildren(nsFrameConstructorState&, nsIContent*, mozilla::ComputedStyle*, nsContainerFrame*, bool, nsFrameList&, bool, nsIFrame*) src/layout/base/nsCSSFrameConstructor.cpp:9661:3
    #28 0x7f14062c5be9 in nsCSSFrameConstructor::ConstructFrameFromItemInternal(nsCSSFrameConstructor::FrameConstructionItem&, nsFrameConstructorState&, nsContainerFrame*, nsFrameList&) src/layout/base/nsCSSFrameConstructor.cpp:3714:9
    #29 0x7f14062ca831 in nsCSSFrameConstructor::ConstructFramesFromItem(nsFrameConstructorState&, nsCSSFrameConstructor::FrameConstructionItemList::Iterator&, nsContainerFrame*, nsFrameList&) src/layout/base/nsCSSFrameConstructor.cpp:5637:3
    #30 0x7f1406346ca5 in nsCSSFrameConstructor::ConstructFramesFromItemList(nsFrameConstructorState&, nsCSSFrameConstructor::FrameConstructionItemList&, nsContainerFrame*, bool, nsFrameList&) src/layout/base/nsCSSFrameConstructor.cpp:9496:5
    #31 0x7f14062b9f57 in nsCSSFrameConstructor::ProcessChildren(nsFrameConstructorState&, nsIContent*, mozilla::ComputedStyle*, nsContainerFrame*, bool, nsFrameList&, bool, nsIFrame*) src/layout/base/nsCSSFrameConstructor.cpp:9661:3
    #32 0x7f14062c5be9 in nsCSSFrameConstructor::ConstructFrameFromItemInternal(nsCSSFrameConstructor::FrameConstructionItem&, nsFrameConstructorState&, nsContainerFrame*, nsFrameList&) src/layout/base/nsCSSFrameConstructor.cpp:3714:9
    #33 0x7f14062ca831 in nsCSSFrameConstructor::ConstructFramesFromItem(nsFrameConstructorState&, nsCSSFrameConstructor::FrameConstructionItemList::Iterator&, nsContainerFrame*, nsFrameList&) src/layout/base/nsCSSFrameConstructor.cpp:5637:3
    #34 0x7f1406346ca5 in nsCSSFrameConstructor::ConstructFramesFromItemList(nsFrameConstructorState&, nsCSSFrameConstructor::FrameConstructionItemList&, nsContainerFrame*, bool, nsFrameList&) src/layout/base/nsCSSFrameConstructor.cpp:9496:5
    #35 0x7f14062b9f57 in nsCSSFrameConstructor::ProcessChildren(nsFrameConstructorState&, nsIContent*, mozilla::ComputedStyle*, nsContainerFrame*, bool, nsFrameList&, bool, nsIFrame*) src/layout/base/nsCSSFrameConstructor.cpp:9661:3
    #36 0x7f14062c5be9 in nsCSSFrameConstructor::ConstructFrameFromItemInternal(nsCSSFrameConstructor::FrameConstructionItem&, nsFrameConstructorState&, nsContainerFrame*, nsFrameList&) src/layout/base/nsCSSFrameConstructor.cpp:3714:9
    #37 0x7f14062ca831 in nsCSSFrameConstructor::ConstructFramesFromItem(nsFrameConstructorState&, nsCSSFrameConstructor::FrameConstructionItemList::Iterator&, nsContainerFrame*, nsFrameList&) src/layout/base/nsCSSFrameConstructor.cpp:5637:3
    #38 0x7f1406346ca5 in nsCSSFrameConstructor::ConstructFramesFromItemList(nsFrameConstructorState&, nsCSSFrameConstructor::FrameConstructionItemList&, nsContainerFrame*, bool, nsFrameList&) src/layout/base/nsCSSFrameConstructor.cpp:9496:5
    #39 0x7f14062b9f57 in nsCSSFrameConstructor::ProcessChildren(nsFrameConstructorState&, nsIContent*, mozilla::ComputedStyle*, nsContainerFrame*, bool, nsFrameList&, bool, nsIFrame*) src/layout/base/nsCSSFrameConstructor.cpp:9661:3
    #40 0x7f14062c5be9 in nsCSSFrameConstructor::ConstructFrameFromItemInternal(nsCSSFrameConstructor::FrameConstructionItem&, nsFrameConstructorState&, nsContainerFrame*, nsFrameList&) src/layout/base/nsCSSFrameConstructor.cpp:3714:9
    #41 0x7f14062ca831 in nsCSSFrameConstructor::ConstructFramesFromItem(nsFrameConstructorState&, nsCSSFrameConstructor::FrameConstructionItemList::Iterator&, nsContainerFrame*, nsFrameList&) src/layout/base/nsCSSFrameConstructor.cpp:5637:3
    #42 0x7f1406346ca5 in nsCSSFrameConstructor::ConstructFramesFromItemList(nsFrameConstructorState&, nsCSSFrameConstructor::FrameConstructionItemList&, nsContainerFrame*, bool, nsFrameList&) src/layout/base/nsCSSFrameConstructor.cpp:9496:5
    #43 0x7f14062b9f57 in nsCSSFrameConstructor::ProcessChildren(nsFrameConstructorState&, nsIContent*, mozilla::ComputedStyle*, nsContainerFrame*, bool, nsFrameList&, bool, nsIFrame*) src/layout/base/nsCSSFrameConstructor.cpp:9661:3
    #44 0x7f14062c5be9 in nsCSSFrameConstructor::ConstructFrameFromItemInternal(nsCSSFrameConstructor::FrameConstructionItem&, nsFrameConstructorState&, nsContainerFrame*, nsFrameList&) src/layout/base/nsCSSFrameConstructor.cpp:3714:9
    #45 0x7f14062ca831 in nsCSSFrameConstructor::ConstructFramesFromItem(nsFrameConstructorState&, nsCSSFrameConstructor::FrameConstructionItemList::Iterator&, nsContainerFrame*, nsFrameList&) src/layout/base/nsCSSFrameConstructor.cpp:5637:3
    #46 0x7f1406346ca5 in nsCSSFrameConstructor::ConstructFramesFromItemList(nsFrameConstructorState&, nsCSSFrameConstructor::FrameConstructionItemList&, nsContainerFrame*, bool, nsFrameList&) src/layout/base/nsCSSFrameConstructor.cpp:9496:5
    #47 0x7f14062b9f57 in nsCSSFrameConstructor::ProcessChildren(nsFrameConstructorState&, nsIContent*, mozilla::ComputedStyle*, nsContainerFrame*, bool, nsFrameList&, bool, nsIFrame*) src/layout/base/nsCSSFrameConstructor.cpp:9661:3
    #48 0x7f14062bec82 in nsCSSFrameConstructor::ConstructBlock(nsFrameConstructorState&, nsIContent*, nsContainerFrame*, nsContainerFrame*, mozilla::ComputedStyle*, nsContainerFrame**, nsFrameList&, nsIFrame*) src/layout/base/nsCSSFrameConstructor.cpp:10562:3
    #49 0x7f14062bcfa6 in nsCSSFrameConstructor::ConstructDocElementFrame(mozilla::dom::Element*, nsILayoutHistoryState*) src/layout/base/nsCSSFrameConstructor.cpp:2336:5
    #50 0x7f14062cd813 in nsCSSFrameConstructor::ContentRangeInserted(nsIContent*, nsIContent*, nsILayoutHistoryState*, nsCSSFrameConstructor::InsertionKind) src/layout/base/nsCSSFrameConstructor.cpp:6974:9
    #51 0x7f14062251b1 in mozilla::PresShell::Initialize() src/layout/base/PresShell.cpp:1733:26
    #52 0x7f14053417f9 in mozilla::dom::PrototypeDocumentContentSink::StartLayout() src/dom/prototype/PrototypeDocumentContentSink.cpp:669:30
    #53 0x7f1405341277 in mozilla::dom::PrototypeDocumentContentSink::DoneWalking() src/dom/prototype/PrototypeDocumentContentSink.cpp:638:3
    #54 0x7f140534100c in mozilla::dom::PrototypeDocumentContentSink::MaybeDoneWalking() src/dom/prototype/PrototypeDocumentContentSink.cpp:614:10
    #55 0x7f1405ccb3c1 in mozilla::dom::DocumentL10n::InitialDocumentTranslationCompleted() src/dom/l10n/DocumentL10n.cpp:225:19
    #56 0x7f1405cd3253 in L10nReadyHandler::ResolvedCallback(JSContext*, JS::Handle<JS::Value>) src/dom/l10n/DocumentL10n.cpp:69:20
    #57 0x7f140580bde1 in mozilla::dom::(anonymous namespace)::PromiseNativeHandlerShim::ResolvedCallback(JSContext*, JS::Handle<JS::Value>) src/dom/promise/Promise.cpp:382:12
    #58 0x7f140580c7e5 in mozilla::dom::NativeHandlerCallback(JSContext*, unsigned int, JS::Value*) src/dom/promise/Promise.cpp
    #59 0x7f140a1d8160 in CallJSNative(JSContext*, bool (*)(JSContext*, unsigned int, JS::Value*), js::CallReason, JS::CallArgs const&) src/js/src/vm/Interpreter.cpp:457:13
    #60 0x7f140a1d8160 in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) src/js/src/vm/Interpreter.cpp:549:12
    #61 0x7f140a1d916a in InternalCall(JSContext*, js::AnyInvokeArgs const&, js::CallReason) src/js/src/vm/Interpreter.cpp:618:10
    #62 0x7f140a1d935d in js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>, js::CallReason) src/js/src/vm/Interpreter.cpp:635:8
    #63 0x7f140a3acca0 in js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, JS::Handle<JS::Value>, JS::MutableHandle<JS::Value>) src/js/src/vm/Interpreter.h:103:10
    #64 0x7f140a6d0df5 in PromiseReactionJob(JSContext*, unsigned int, JS::Value*) src/js/src/builtin/Promise.cpp:1832:10
    #65 0x7f140a1d8160 in CallJSNative(JSContext*, bool (*)(JSContext*, unsigned int, JS::Value*), js::CallReason, JS::CallArgs const&) src/js/src/vm/Interpreter.cpp:457:13
    #66 0x7f140a1d8160 in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) src/js/src/vm/Interpreter.cpp:549:12
    #67 0x7f140a1d916a in InternalCall(JSContext*, js::AnyInvokeArgs const&, js::CallReason) src/js/src/vm/Interpreter.cpp:618:10
    #68 0x7f140a1d935d in js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>, js::CallReason) src/js/src/vm/Interpreter.cpp:635:8
    #69 0x7f140a42845b in JS::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, JS::HandleValueArray const&, JS::MutableHandle<JS::Value>) src/js/src/jsapi.cpp:2753:10
    #70 0x7f140257cbf7 in mozilla::dom::PromiseJobCallback::Call(JSContext*, JS::Handle<JS::Value>, mozilla::ErrorResult&) src/objdir-ff-ubsan/dom/bindings/PromiseBinding.cpp:27:8
    #71 0x7f13fd4c8b27 in mozilla::dom::PromiseJobCallback::Call(mozilla::ErrorResult&, char const*, mozilla::dom::CallbackObject::ExceptionHandling, JS::Realm*) src/objdir-ff-ubsan/dist/include/mozilla/dom/PromiseBinding.h:91:12
    #72 0x7f13fd4c84ec in mozilla::dom::PromiseJobCallback::Call(char const*) src/objdir-ff-ubsan/dist/include/mozilla/dom/PromiseBinding.h:104:12
    #73 0x7f13fd4c71fe in mozilla::PromiseJobRunnable::Run(mozilla::AutoSlowOperation&) src/xpcom/base/CycleCollectedJSContext.cpp:208:18
    #74 0x7f13fd491674 in mozilla::CycleCollectedJSContext::PerformMicroTaskCheckPoint(bool) src/xpcom/base/CycleCollectedJSContext.cpp:626:17
    #75 0x7f13fd491c64 in mozilla::CycleCollectedJSContext::AfterProcessTask(unsigned int) src/xpcom/base/CycleCollectedJSContext.cpp:455:3
    #76 0x7f13ffe2f5dd in XPCJSContext::AfterProcessTask(unsigned int) src/js/xpconnect/src/XPCJSContext.cpp:1319:28
    #77 0x7f13fd6f901b in nsThread::ProcessNextEvent(bool, bool*) src/xpcom/threads/nsThread.cpp:1319:24
    #78 0x7f13fd6fe74e in NS_ProcessNextEvent(nsIThread*, bool) src/xpcom/threads/nsThreadUtils.cpp:486:10
    #79 0x7f13feae1e4e in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) src/ipc/glue/MessagePump.cpp:87:21
    #80 0x7f13fe924b04 in MessageLoop::Run() src/ipc/chromium/src/base/message_loop.cc:290:3
    #81 0x7f1405dde03a in nsBaseAppShell::Run() src/widget/nsBaseAppShell.cpp:137:27
    #82 0x7f1409cdaea4 in nsAppStartup::Run() src/toolkit/components/startup/nsAppStartup.cpp:272:30
    #83 0x7f1409eca11b in XREMain::XRE_mainRun() src/toolkit/xre/nsAppRunner.cpp:4600:22
    #84 0x7f1409ecb588 in XREMain::XRE_main(int, char**, mozilla::BootstrapConfig const&) src/toolkit/xre/nsAppRunner.cpp:4737:8
    #85 0x7f1409ecc14b in XRE_main(int, char**, mozilla::BootstrapConfig const&) src/toolkit/xre/nsAppRunner.cpp:4818:21
    #86 0x55a3586a5df2 in do_main(int, char**, char**) src/browser/app/nsBrowserApp.cpp:217:22
    #87 0x55a3586a5500 in main src/browser/app/nsBrowserApp.cpp:339:16

Huh, I didn't know that you couldn't use co-variant return types when dealing with function pointers like this. The reason we don't fail when compiling is that we cast the function pointer to the version that returns nsIFrame* here:

https://searchfox.org/mozilla-central/rev/62a130ba0ac80f75175e4b65536290b52391f116/layout/base/nsCSSFrameConstructor.cpp#311-312

It would be a little annoying to work around this, since we rely on some of these factory functions returning nsContainerFrame*, and some returning nsBlockFrame*, for some simple type checking (see the ContainerFrameCreationFunc and BlockFrameCreationFunc typedefs).

We could add a third member to the FrameConstructionData::mFunc union for functions that return nsContainerFrame*, make the FCDATA_DECL macro and friends check the return type of the function and assign it to the right union member, and add some flag indicating which union member to look at when fetching the function pointer. And hopefully that would all get optimized away by the compiler.

Tyson, do you know if instead there is a way to make our compilers not treat this as UB?

Flags: needinfo?(twsmith)

Maybe we can use std::function<> to allow this?

std::function<> has a non-trivial destructor, and so would require adding a destructor to the union. Maybe that's fine, and we can just not call the std::function<>'s destructor, as we know we only use plain function pointers and not functor objects that might really need destruction...

What would make using std::function not ub?

We could also make use of the magic C++-lambda-that-coerces-to-function-pointer like this:

[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewGridContainerFrame(aPs, aStyle); }

But that may involve two function calls instead of one...

I think C++ allows conversion of function pointers to std::function with the co-variance of return type that we want. At least, when I removed the explicit casts from FCDATA_DECL, I got compile errors, and when I switched to using std::function still without the casts, the compile errors went away.

Assignee: nobody → cam

(In reply to Emilio Cobos Álvarez (:emilio) from comment #6)

We could also make use of the magic C++-lambda-that-coerces-to-function-pointer like this:

[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewGridContainerFrame(aPs, aStyle); }

That's a neat trick, I think that would work too. And hopefully the compiler doesn't actually perform two function calls but who knows. :-)

Anyway, stuck a patch up with the std::function usage, and tagged you and Gerald (for C++ expertness) for review.

Attached file codegen test-case

(I don't trust compilers anymore :/)

OK so trying that in godbolt.org std::function causes a whole heap of extra stuff to go on...

I wonder if the sanitizer complains if we make the function in the union a void*...

(I meant returning void* above). Anyhow, if this is not avoidable, the lambda hack seems an slightly-less-bad option, as it only involves one more instruction (it seems to get compiled to a tail call which is just an extra jump). Not great but...

(I reckon that still probably counts as an invalid function pointer conversion.)

Adding union members per the middle paragraph of comment 2, and then using some of the bits to distinguish which member to call through, still doesn't optimize down to what we have currently. :( https://godbolt.org/z/JxcVnL

Attachment #9115351 - Attachment is obsolete: true

Or we just change all the factory functions to return nsIFrame*, lose the type checking in ConstructFrameWithAnonymousChild etc. and replace it with assertions, and add a few casts to callers...

I guess this is unambiguously UB:

http://eel.is/c++draft/expr.call#6:

Calling a function through an expression whose function type is different from the function type of the called function's definition results in undefined behavior.

http://eel.is/c++draft/expr.reinterpret.cast#6:

A function pointer can be explicitly converted to a function pointer of a different type. [ Note: The effect of calling a function through a pointer to a function type ([dcl.fct]) that is not the same as the type used in the definition of the function is undefined ([expr.call]). — end note ] Except that converting a prvalue of type “pointer to T1” to the type “pointer to T2” (where T1 and T2 are function types) and back to its original type yields the original pointer value, the result of such a pointer conversion is unspecified. [ Note: See also [conv.ptr] for more details of pointer conversions. — end note ]

In terms of how to solve this, the lambda is probably less friction, but comment 15 seems also ok I guess.

Priority: -- → P3

(In reply to Cameron McCormack (:heycam) (away 21 Dec – 6 Jan) from comment #2)

Tyson, do you know if instead there is a way to make our compilers not treat this as UB?

AFAIK our options are 1) change the code to remove UB or 2) add it to a suppression list. Sorry I wish I had better news.

Flags: needinfo?(twsmith)
Assignee: cam → nobody

Avoid storing functions with the wrong return type by wrapping them
trivially on a lambda (in ToCreatorFunc).

This gets compiled to a tail call so it's just one more instruction, and
the constexpr constructors should ensure we don't introduce static
inintializers (which is why we used macros in the past).

Assignee: nobody → emilio
Status: NEW → ASSIGNED
Pushed by ealvarez@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/823a37a9ec45
Fix UB in FrameConstructionData. r=layout-reviewers,jfkthame
Pushed by emilio@crisal.io:
https://hg.mozilla.org/integration/autoland/rev/d86ddd63c994
Sprinkle some implicit/explicit to keep static analysis happy.
Status: ASSIGNED → RESOLVED
Closed: 2 years ago
Resolution: --- → FIXED
Target Milestone: --- → 97 Branch
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: