heap-buffer-overflow in [@ gfxFont::DrawEmphasisMarks]
Categories
(Core :: Layout: Text and Fonts, defect)
Tracking
()
People
(Reporter: tsmith, Assigned: jfkthame)
References
(Blocks 1 open bug, Regression)
Details
(Keywords: csectype-bounds, regression, sec-high, Whiteboard: [sec-survey][adv-main85+r])
Attachments
(1 file)
48 bytes,
text/x-phabricator-request
|
dveditz
:
approval-mozilla-beta+
dveditz
:
sec-approval+
|
Details | Review |
A test case will be attached once reduction is complete.
==11807==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6180000ce3cc at pc 0x7fa615a857f1 bp 0x7ffd38c18b10 sp 0x7ffd38c18b08
READ of size 4 at 0x6180000ce3cc thread T0 (Web Content)
#0 0x7fa615a857f0 in IsSimpleGlyph /builds/worker/workspace/obj-build/dist/include/gfxFont.h:804:41
#1 0x7fa615a857f0 in IsClusterStart /builds/worker/workspace/obj-build/dist/include/gfxFont.h:818:14
#2 0x7fa615a857f0 in IsClusterStart /builds/worker/workspace/obj-build/dist/include/gfxTextRun.h:109:35
#3 0x7fa615a857f0 in gfxFont::DrawEmphasisMarks(gfxTextRun const*, mozilla::gfx::PointTyped<mozilla::gfx::UnknownUnits, float>*, unsigned int, unsigned int, EmphasisMarkDrawParams const&) src/gfx/thebes/gfxFont.cpp:2031:42
#4 0x7fa615bc5aa5 in gfxTextRun::DrawEmphasisMarks(gfxContext*, gfxTextRun*, double, mozilla::gfx::PointTyped<mozilla::gfx::UnknownUnits, float>, gfxTextRun::Range, gfxTextRun::PropertyProvider*) const src/gfx/thebes/gfxTextRun.cpp:739:11
#5 0x7fa61b6c272c in nsTextFrame::DrawEmphasisMarks(gfxContext*, mozilla::WritingMode, mozilla::gfx::PointTyped<mozilla::gfx::UnknownUnits, float> const&, mozilla::gfx::PointTyped<mozilla::gfx::UnknownUnits, float> const&, gfxTextRun::Range, unsigned int const*, nsTextFrame::PropertyProvider*) src/layout/generic/nsTextFrame.cpp:6525:15
#6 0x7fa61b6c8e13 in nsTextFrame::DrawTextRunAndDecorations(gfxTextRun::Range, mozilla::gfx::PointTyped<mozilla::gfx::UnknownUnits, float> const&, nsTextFrame::DrawTextParams const&, nsTextFrame::TextDecorations const&) src/layout/generic/nsTextFrame.cpp:7144:3
#7 0x7fa61b6bcd95 in nsTextFrame::DrawText(gfxTextRun::Range, mozilla::gfx::PointTyped<mozilla::gfx::UnknownUnits, float> const&, nsTextFrame::DrawTextParams const&) src/layout/generic/nsTextFrame.cpp:7176:5
#8 0x7fa61b6c547e in nsTextFrame::PaintText(nsTextFrame::PaintTextParams const&, int, int, nsPoint const&, bool, float) src/layout/generic/nsTextFrame.cpp:6866:3
#9 0x7fa61bacc05b in nsDisplayText::RenderToContext(gfxContext*, nsDisplayListBuilder*, bool) src/layout/painting/nsDisplayList.cpp:9054:6
#10 0x7fa61bacc79f in nsDisplayText::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder&, mozilla::wr::IpcResourceUpdateQueue&, mozilla::layers::StackingContextHelper const&, mozilla::layers::RenderRootStateManager*, nsDisplayListBuilder*) src/layout/painting/nsDisplayList.cpp:8980:3
#11 0x7fa615602d00 in mozilla::layers::WebRenderCommandBuilder::CreateWebRenderCommands(nsDisplayItem*, mozilla::wr::DisplayListBuilder&, mozilla::wr::IpcResourceUpdateQueue&, mozilla::layers::StackingContextHelper const&, nsDisplayListBuilder*) src/gfx/layers/wr/WebRenderCommandBuilder.cpp:1655:41
#12 0x7fa615600f04 in mozilla::layers::WebRenderCommandBuilder::CreateWebRenderCommandsFromDisplayList(nsDisplayList*, nsDisplayItem*, nsDisplayListBuilder*, mozilla::layers::StackingContextHelper const&, mozilla::wr::DisplayListBuilder&, mozilla::wr::IpcResourceUpdateQueue&) src/gfx/layers/wr/WebRenderCommandBuilder.cpp:1778:7
#13 0x7fa61baad443 in nsDisplayWrapList::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder&, mozilla::wr::IpcResourceUpdateQueue&, mozilla::layers::StackingContextHelper const&, mozilla::layers::RenderRootStateManager*, nsDisplayListBuilder*) src/layout/painting/nsDisplayList.cpp:5709:30
#14 0x7fa61bab4238 in nsDisplayOwnLayer::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder&, mozilla::wr::IpcResourceUpdateQueue&, mozilla::layers::StackingContextHelper const&, mozilla::layers::RenderRootStateManager*, nsDisplayListBuilder*) src/layout/painting/nsDisplayList.cpp:6458:22
#15 0x7fa615602d00 in mozilla::layers::WebRenderCommandBuilder::CreateWebRenderCommands(nsDisplayItem*, mozilla::wr::DisplayListBuilder&, mozilla::wr::IpcResourceUpdateQueue&, mozilla::layers::StackingContextHelper const&, nsDisplayListBuilder*) src/gfx/layers/wr/WebRenderCommandBuilder.cpp:1655:41
#16 0x7fa615600f04 in mozilla::layers::WebRenderCommandBuilder::CreateWebRenderCommandsFromDisplayList(nsDisplayList*, nsDisplayItem*, nsDisplayListBuilder*, mozilla::layers::StackingContextHelper const&, mozilla::wr::DisplayListBuilder&, mozilla::wr::IpcResourceUpdateQueue&) src/gfx/layers/wr/WebRenderCommandBuilder.cpp:1778:7
#17 0x7fa6155ff59a in mozilla::layers::WebRenderCommandBuilder::BuildWebRenderCommands(mozilla::wr::DisplayListBuilder&, mozilla::wr::IpcResourceUpdateQueue&, nsDisplayList*, nsDisplayListBuilder*, mozilla::layers::WebRenderScrollData&, WrFiltersHolder&&) src/gfx/layers/wr/WebRenderCommandBuilder.cpp:1581:5
#18 0x7fa61561b4a5 in mozilla::layers::WebRenderLayerManager::EndTransactionWithoutLayer(nsDisplayList*, nsDisplayListBuilder*, WrFiltersHolder&&, mozilla::layers::WebRenderBackgroundData*) src/gfx/layers/wr/WebRenderLayerManager.cpp:368:30
#19 0x7fa61ba89031 in nsDisplayList::PaintRoot(nsDisplayListBuilder*, gfxContext*, unsigned int) src/layout/painting/nsDisplayList.cpp:2494:18
#20 0x7fa61b32637a in nsLayoutUtils::PaintFrame(gfxContext*, nsIFrame*, nsRegion const&, unsigned int, nsDisplayListBuilderMode, nsLayoutUtils::PaintFrameFlags) src/layout/base/nsLayoutUtils.cpp:3433:13
#21 0x7fa61b227ed0 in mozilla::PresShell::Paint(nsView*, nsRegion const&, mozilla::PaintFlags) src/layout/base/PresShell.cpp:6389:5
#22 0x7fa61abcd24e in nsViewManager::ProcessPendingUpdatesPaint(nsIWidget*) src/view/nsViewManager.cpp:460:18
#23 0x7fa61abcc8be in nsViewManager::ProcessPendingUpdatesForView(nsView*, bool) src/view/nsViewManager.cpp:395:22
#24 0x7fa61abcf2cc in nsViewManager::ProcessPendingUpdates() src/view/nsViewManager.cpp:1018:5
#25 0x7fa61b19cc1f in nsRefreshDriver::Tick(mozilla::layers::BaseTransactionId<mozilla::VsyncIdType>, mozilla::TimeStamp) src/layout/base/nsRefreshDriver.cpp:2375:11
#26 0x7fa61b1a9509 in TickDriver src/layout/base/nsRefreshDriver.cpp:357:13
#27 0x7fa61b1a9509 in mozilla::RefreshDriverTimer::TickRefreshDrivers(mozilla::layers::BaseTransactionId<mozilla::VsyncIdType>, mozilla::TimeStamp, nsTArray<RefPtr<nsRefreshDriver> >&) src/layout/base/nsRefreshDriver.cpp:336:7
#28 0x7fa61b1a9181 in mozilla::RefreshDriverTimer::Tick(mozilla::layers::BaseTransactionId<mozilla::VsyncIdType>, mozilla::TimeStamp) src/layout/base/nsRefreshDriver.cpp:351:5
#29 0x7fa61b1a8394 in RunRefreshDrivers src/layout/base/nsRefreshDriver.cpp:799:5
#30 0x7fa61b1a8394 in mozilla::VsyncRefreshDriverTimer::RefreshDriverVsyncObserver::TickRefreshDriver(mozilla::layers::BaseTransactionId<mozilla::VsyncIdType>, mozilla::TimeStamp) src/layout/base/nsRefreshDriver.cpp:722:16
#31 0x7fa61b1a77d5 in mozilla::VsyncRefreshDriverTimer::RefreshDriverVsyncObserver::NotifyParentProcessVsync() src/layout/base/nsRefreshDriver.cpp:624:7
#32 0x7fa61b1a6f90 in mozilla::VsyncRefreshDriverTimer::RefreshDriverVsyncObserver::NotifyVsync(mozilla::VsyncEvent const&) src/layout/base/nsRefreshDriver.cpp:545:9
#33 0x7fa61a2e2f07 in mozilla::dom::VsyncChild::RecvNotify(mozilla::VsyncEvent const&, float const&) src/dom/ipc/VsyncChild.cpp:69:15
#34 0x7fa61481f47c in mozilla::dom::PVsyncChild::OnMessageReceived(IPC::Message const&) /builds/worker/workspace/obj-build/ipc/ipdl/PVsyncChild.cpp:178:54
#35 0x7fa6144105f4 in mozilla::ipc::PBackgroundChild::OnMessageReceived(IPC::Message const&) /builds/worker/workspace/obj-build/ipc/ipdl/PBackgroundChild.cpp:6286:32
#36 0x7fa613e6767e in mozilla::ipc::MessageChannel::DispatchAsyncMessage(mozilla::ipc::ActorLifecycleProxy*, IPC::Message const&) src/ipc/glue/MessageChannel.cpp:2153:25
#37 0x7fa613e634e4 in mozilla::ipc::MessageChannel::DispatchMessage(IPC::Message&&) src/ipc/glue/MessageChannel.cpp:2077:9
#38 0x7fa613e652e8 in mozilla::ipc::MessageChannel::RunMessage(mozilla::ipc::MessageChannel::MessageTask&) src/ipc/glue/MessageChannel.cpp:1925:3
#39 0x7fa613e65f08 in mozilla::ipc::MessageChannel::MessageTask::Run() src/ipc/glue/MessageChannel.cpp:1956:13
#40 0x7fa612b3ea59 in mozilla::RunnableTask::Run() src/xpcom/threads/TaskController.cpp:459:16
#41 0x7fa612b3b457 in mozilla::TaskController::DoExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) src/xpcom/threads/TaskController.cpp:739:26
#42 0x7fa612b39397 in mozilla::TaskController::ExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) src/xpcom/threads/TaskController.cpp:598:15
#43 0x7fa612b397ed in mozilla::TaskController::ProcessPendingMTTask(bool) src/xpcom/threads/TaskController.cpp:382:36
#44 0x7fa612b465d1 in operator() src/xpcom/threads/TaskController.cpp:123:37
#45 0x7fa612b465d1 in mozilla::detail::RunnableFunction<mozilla::TaskController::InitializeInternal()::$_3>::Run() /builds/worker/workspace/obj-build/dist/include/nsThreadUtils.h:534:5
#46 0x7fa612b66b2d in nsThread::ProcessNextEvent(bool, bool*) src/xpcom/threads/nsThread.cpp:1200:14
#47 0x7fa612b71e5c in NS_ProcessNextEvent(nsIThread*, bool) src/xpcom/threads/nsThreadUtils.cpp:548:10
#48 0x7fa613e7029f in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) src/ipc/glue/MessagePump.cpp:87:21
#49 0x7fa613d66b31 in RunInternal src/ipc/chromium/src/base/message_loop.cc:334:10
#50 0x7fa613d66b31 in RunHandler src/ipc/chromium/src/base/message_loop.cc:327:3
#51 0x7fa613d66b31 in MessageLoop::Run() src/ipc/chromium/src/base/message_loop.cc:309:3
#52 0x7fa61ac8e9b7 in nsBaseAppShell::Run() src/widget/nsBaseAppShell.cpp:137:27
#53 0x7fa61e9c9c3f in XRE_RunAppShell() src/toolkit/xre/nsEmbedFunctions.cpp:902:20
#54 0x7fa613d66b31 in RunInternal src/ipc/chromium/src/base/message_loop.cc:334:10
#55 0x7fa613d66b31 in RunHandler src/ipc/chromium/src/base/message_loop.cc:327:3
#56 0x7fa613d66b31 in MessageLoop::Run() src/ipc/chromium/src/base/message_loop.cc:309:3
#57 0x7fa61e9c91dc in XRE_InitChildProcess(int, char**, XREChildData const*) src/toolkit/xre/nsEmbedFunctions.cpp:733:34
#58 0x561f6e4cbbdd in content_process_main(mozilla::Bootstrap*, int, char**) src/browser/app/../../ipc/contentproc/plugin-container.cpp:57:28
#59 0x561f6e4cc017 in main src/browser/app/nsBrowserApp.cpp:305:18
#60 0x7fa63a1d2b96 in __libc_start_main /build/glibc-2ORdQG/glibc-2.27/csu/../csu/libc-start.c:310
#61 0x561f6e41f579 in _start (/home/twsmith/workspace/browsers/m-c-20201227212342-fuzzing-asan-opt/firefox+0x5a579)
0x6180000ce3cc is located 0 bytes to the right of 844-byte region [0x6180000ce080,0x6180000ce3cc)
allocated by thread T0 (Web Content) here:
#0 0x561f6e49940d in malloc /builds/worker/fetches/llvm-project/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cpp:145:3
#1 0x7fa615bbfb47 in gfxTextRun::AllocateStorageForTextRun(unsigned long, unsigned int) src/gfx/thebes/gfxTextRun.cpp:130:19
#2 0x7fa61b6dd628 in nsTransformedTextRun::Create(gfxTextRunFactory::Parameters const*, nsTransformingTextRunFactory*, gfxFontGroup*, char16_t const*, unsigned int, mozilla::gfx::ShapedTextFlags, nsTextFrameUtils::Flags, nsTArray<RefPtr<nsTransformedCharStyle> >&&, bool) src/layout/generic/nsTextRunTransformations.cpp:48:7
#3 0x7fa61b695495 in MakeTextRun src/layout/generic/nsTextRunTransformations.cpp:103:10
#4 0x7fa61b695495 in BuildTextRunsScanner::BuildTextRunForFrames(void*) src/layout/generic/nsTextFrame.cpp:2539:38
#5 0x7fa61b691946 in BuildTextRunsScanner::FlushFrames(bool, bool) src/layout/generic/nsTextFrame.cpp:1662:17
#6 0x7fa61b69de29 in BuildTextRuns src/layout/generic/nsTextFrame.cpp:1586:11
#7 0x7fa61b69de29 in nsTextFrame::EnsureTextRun(nsTextFrame::TextRunType, mozilla::gfx::DrawTarget*, nsIFrame*, nsLineList_iterator const*, unsigned int*) src/layout/generic/nsTextFrame.cpp:3003:7
#8 0x7fa61b6d433b in nsTextFrame::AddInlinePrefISizeForFlow(gfxContext*, nsIFrame::InlinePrefISizeData*, nsTextFrame::TextRunType) src/layout/generic/nsTextFrame.cpp:8531:7
#9 0x7fa61b6d5606 in nsTextFrame::AddInlinePrefISize(gfxContext*, nsIFrame::InlinePrefISizeData*) src/layout/generic/nsTextFrame.cpp:8669:10
#10 0x7fa61b3f92ee in nsBlockFrame::GetPrefISize(gfxContext*) src/layout/generic/nsBlockFrame.cpp:904:16
#11 0x7fa61b32e730 in nsLayoutUtils::IntrinsicForAxis(mozilla::PhysicalAxis, gfxContext*, nsIFrame*, mozilla::IntrinsicISizeType, mozilla::Maybe<mozilla::LogicalSize> const&, unsigned int, int) src/layout/base/nsLayoutUtils.cpp
#12 0x7fa61b33102c in nsLayoutUtils::IntrinsicForContainer(gfxContext*, nsIFrame*, mozilla::IntrinsicISizeType, unsigned int) src/layout/base/nsLayoutUtils.cpp:4954:10
#13 0x7fa61b96b681 in nsMathMLContainerFrame::GetIntrinsicISizeMetrics(gfxContext*, mozilla::ReflowOutput&) src/layout/mathml/nsMathMLContainerFrame.cpp:962:23
#14 0x7fa61b96b65c in nsMathMLContainerFrame::GetIntrinsicISizeMetrics(gfxContext*, mozilla::ReflowOutput&) src/layout/mathml/nsMathMLContainerFrame.cpp:956:23
#15 0x7fa61b96af0c in UpdateIntrinsicWidth src/layout/mathml/nsMathMLContainerFrame.cpp:919:5
#16 0x7fa61b96af0c in nsMathMLContainerFrame::GetMinISize(gfxContext*) src/layout/mathml/nsMathMLContainerFrame.cpp:932:3
#17 0x7fa61b46195f in ShrinkWidthToFit src/layout/generic/nsIFrame.cpp:6470:22
#18 0x7fa61b46195f in nsContainerFrame::ComputeAutoSize(gfxContext*, mozilla::WritingMode, mozilla::LogicalSize const&, int, mozilla::LogicalSize const&, mozilla::LogicalSize const&, mozilla::EnumSet<mozilla::ComputeSizeFlag, unsigned char>) src/layout/generic/nsContainerFrame.cpp:998:11
#19 0x7fa61b474f74 in nsIFrame::ComputeSize(gfxContext*, mozilla::WritingMode, mozilla::LogicalSize const&, int, mozilla::LogicalSize const&, mozilla::LogicalSize const&, mozilla::EnumSet<mozilla::ComputeSizeFlag, unsigned char>) src/layout/generic/nsIFrame.cpp:6097:7
#20 0x7fa61b3b55de in mozilla::ReflowInput::InitConstraints(nsPresContext*, mozilla::Maybe<mozilla::LogicalSize> const&, mozilla::Maybe<mozilla::LogicalMargin> const&, mozilla::Maybe<mozilla::LogicalMargin> const&, mozilla::LayoutFrameType) src/layout/generic/ReflowInput.cpp:2423:27
#21 0x7fa61b3af1f6 in mozilla::ReflowInput::Init(nsPresContext*, mozilla::Maybe<mozilla::LogicalSize> const&, mozilla::Maybe<mozilla::LogicalMargin> const&, mozilla::Maybe<mozilla::LogicalMargin> const&) src/layout/generic/ReflowInput.cpp:350:3
#22 0x7fa61b3b0413 in mozilla::ReflowInput::ReflowInput(nsPresContext*, mozilla::ReflowInput const&, nsIFrame*, mozilla::LogicalSize const&, mozilla::Maybe<mozilla::LogicalSize> const&, mozilla::EnumSet<mozilla::ReflowInput::InitFlag, unsigned char>, mozilla::EnumSet<mozilla::ComputeSizeFlag, unsigned char>) src/layout/generic/ReflowInput.cpp:213:5
#23 0x7fa61b65013d in void mozilla::Maybe<mozilla::ReflowInput>::emplace<nsPresContext*&, mozilla::ReflowInput const&, nsIFrame*&, mozilla::LogicalSize&>(nsPresContext*&, mozilla::ReflowInput const&, nsIFrame*&, mozilla::LogicalSize&) /builds/worker/workspace/obj-build/dist/include/mozilla/Maybe.h:864:39
Reporter | ||
Comment 1•3 years ago
|
||
A Pernosco session is available here: https://pernos.co/debug/qAXj5TiEttfWGhUP3vXqnw/index.html
Comment 2•3 years ago
|
||
Heap overflow related to fonts in WebRender. Lee any thoughts here?
Updated•3 years ago
|
Updated•3 years ago
|
Updated•3 years ago
|
Updated•3 years ago
|
Reporter | ||
Updated•3 years ago
|
Comment 3•3 years ago
|
||
The component has been changed since the backlog priority was decided, so we're resetting it.
For more information, please visit auto_nag documentation.
Assignee | ||
Comment 4•3 years ago
|
||
Hi Tyson - were you able to get anywhere with reducing a testcase here? I'd be interested to take a look. Thanks!
Assignee | ||
Comment 5•3 years ago
|
||
Ah, never mind: I think I found the root cause of this. It's a regression from bug 1663230, where the responsibility for calling ResetGlyphRuns() on the destination textrun was moved from MergeCharactersInTextRun to its caller, but this was only done properly for nsCaseTransformTextRunFactory::RebuildTextRun; I missed the similar callsite in MathMLTextRunFactory::RebuildTextRun.
Assignee | ||
Comment 6•3 years ago
|
||
This matches how it's done at the other callsite.
(Also add an assertion that would've caught the omission sooner.)
Updated•3 years ago
|
Assignee | ||
Comment 7•3 years ago
|
||
Tyson, if you have a testcase you can use to verify the above patch, that'd be awesome - thanks! (But in any case I'm pretty confident it's the right fix, based on observing the behavior in the pernosco trace.)
Reporter | ||
Comment 8•3 years ago
|
||
(In reply to Jonathan Kew (:jfkthame) from comment #7)
Tyson, if you have a testcase you can use to verify the above patch, that'd be awesome - thanks! (But in any case I'm pretty confident it's the right fix, based on observing the behavior in the pernosco trace.)
I do have a test case but it requires manually reduction and it is stubborn. In it's current state is it reliable. I was able to verify that the crash is no longer reproducible with the patch applied.
Assignee | ||
Comment 9•3 years ago
|
||
Comment on attachment 9195407 [details]
Bug 1684497 - Hoist ResetGlyphRuns out of the conditional statement. r=heycam
Security Approval Request
- How easily could an exploit be constructed based on the patch?: The patch is clearly related to MathML text-transform operations, but I don't think it makes it obvious how this could be turned into an exploit. It's unclear to me whether anything more serious than out-of-bounds data reads could be achieved, which could result in a crash or potential leakage of private info, but not arbitrary escalation.
- Do comments in the patch, the check-in comment, or tests included in the patch paint a bulls-eye on the security problem?: No
- Which older supported branches are affected by this flaw?: Firefox 82+
- If not all supported branches, which bug introduced the flaw?: Bug 1663230
- Do you have backports for the affected branches?: No
- If not, how different, hard to create, and risky will they be?: Backport should be trivial.
- How likely is this patch to cause regressions; how much testing does it need?: Minimal regression risk, no special testing required; existing reftests will exercise the codepath in general, and the specific failure case found by fuzzing has been verified.
Updated•3 years ago
|
Updated•3 years ago
|
Comment 10•3 years ago
|
||
Comment on attachment 9195407 [details]
Bug 1684497 - Hoist ResetGlyphRuns out of the conditional statement. r=heycam
sec-approval+, a=dveditz for beta uplift into 85.
Updated•3 years ago
|
Comment 11•3 years ago
|
||
Comment 12•3 years ago
|
||
Comment 13•3 years ago
|
||
uplift |
Comment 14•3 years ago
|
||
As part of a security bug pattern analysis, we are requesting your help with a high level analysis of this bug. It is our hope to develop static analysis (or potentially runtime/dynamic analysis) in the future to identify classes of bugs.
Please visit this google form to reply.
Updated•3 years ago
|
Assignee | ||
Updated•3 years ago
|
Updated•3 years ago
|
Updated•3 years ago
|
Updated•3 years ago
|
Description
•