Closed Bug 322345 Opened 19 years ago Closed 18 years ago

strange crash in svg scale transform (int overflow?)

Categories

(Core :: SVG, defect)

x86
Linux
defect
Not set
normal

Tracking

()

VERIFIED FIXED

People

(Reporter: guninski, Assigned: roc)

Details

(Keywords: crash, verified1.8.0.9, verified1.8.1.1, Whiteboard: [sg:critical?])

Attachments

(3 files)

strange crash in svg scale transform (int overflow?)

there is a strange svg crash, may be due to integer overflow.
the following crashes in memset on linux:

<text font-size="20" transform="scale(16385,16385)">
feck</text>

testcase to follow.

both 1.5 and trunk crash.
Attached file testcase
Component: General → SVG
Product: Firefox → Core
Version: 1.5 Branch → Trunk
roc, can you look at this?
Assignee: nobody → roc
may be a duplicate of Bug 333861 which works from html on trunk only.
this seems fixed on trunk, but both branches crash badly in memset
Flags: blocking1.8.1.1?
Flags: blocking1.8.0.8?
Keywords: crash
Whiteboard: [sg:critical?] fixed on trunk, dupe?
Restoring lost blocking flag
Flags: blocking1.8.0.9?
this still crashes 1.5-latest and 2.0-latest.

a modification of it crashes trunk-latest with a scary stack in memset(3).
macosx and wine seem unaffected.
Doesn't crash either win32 or linux trunk here.
bclary may have linux boxen for testing.

bclary: do you crash on linux trunk with the second attachment and on linux branches with the first one?
Memory crashes scare us, can we investigate and get some kind of fix in? The fact that it's linux-only may hint that the bug is in the linux libraries that are out of our direct control. And maybe it doesn't happen to tor because he's using different libraries?

Can we track this down and file bugs against our upstreams if necessary?
Flags: blocking1.8.1.1?
Flags: blocking1.8.1.1+
Flags: blocking1.8.0.9?
Flags: blocking1.8.0.9+
imho it may be a library outside mozilla, something linux specific in
mozilla or combination of both.

suggest spamming upstream cairo or libfreetype.

here is a valgrind log - seems to stop ealrlier than ff with gdb.

valgrind on debug trunk.

** nsSVGTextFrame::DidSetStyleContext
==26277== 
==26277== Invalid write of size 1
==26277==    at 0x4020173: memset (in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so)
==26277==    by 0x49C828D: (within /usr/lib/libfreetype.so.6.3.10)
==26277==    by 0x49C5F34: (within /usr/lib/libfreetype.so.6.3.10)
==26277==    by 0x49C7202: (within /usr/lib/libfreetype.so.6.3.10)
==26277==    by 0x4989D30: FT_Outline_Render (in /usr/lib/libfreetype.so.6.3.10)
==26277==    by 0x614ED8B: ???
==26277==    by 0x1D1C8: ???
==26277==  Address 0xBC21F27 is not stack'd, malloc'd or (recently) free'd
==26277== 
==26277== Invalid write of size 1
==26277==    at 0x4020179: memset (in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so)
==26277==    by 0x49C828D: (within /usr/lib/libfreetype.so.6.3.10)
==26277==    by 0x49C5F34: (within /usr/lib/libfreetype.so.6.3.10)
==26277==    by 0x49C7202: (within /usr/lib/libfreetype.so.6.3.10)
==26277==    by 0x4989D30: FT_Outline_Render (in /usr/lib/libfreetype.so.6.3.10)
==26277==    by 0x614ED8B: ???
==26277==    by 0x1D1C8: ???
==26277==  Address 0xBC21F29 is not stack'd, malloc'd or (recently) free'd

valgrind: m_mallocfree.c:194 (get_bszB_as_is): Assertion 'bszB_lo == bszB_hi' failed.
valgrind: Heap block lo/hi size mismatch: lo = 624497, hi = 2728567458.
Probably caused by overrunning/underrunning a heap block's bounds.

==26277==    at 0x380133A2: (within /usr/lib/valgrind/x86-linux/memcheck)
==26277==    by 0x380135DE: (within /usr/lib/valgrind/x86-linux/memcheck)
==26277==    by 0x3801AF3F: (within /usr/lib/valgrind/x86-linux/memcheck)
==26277==    by 0x3802DA19: (within /usr/lib/valgrind/x86-linux/memcheck)
==26277==    by 0x38001D0A: (within /usr/lib/valgrind/x86-linux/memcheck)
==26277==    by 0x3802E01B: (within /usr/lib/valgrind/x86-linux/memcheck)
==26277==    by 0x3802F498: (within /usr/lib/valgrind/x86-linux/memcheck)
==26277==    by 0x38043D79: (within /usr/lib/valgrind/x86-linux/memcheck)

sched status:
  running_tid=1
Thread 1: status = VgTs_Runnable
==26277==    at 0x401E65C: calloc (in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so)
==26277==    by 0x40E98FA: _get_bitmap_surface (cairo-ft-font.c:812)
==26277==    by 0x40E9E8E: _render_glyph_outline (cairo-ft-font.c:1017)
==26277==    by 0x40EB8CE: _cairo_ft_scaled_glyph_init (cairo-ft-font.c:1906)
==26277==    by 0x40CBE4D: _cairo_scaled_glyph_lookup (cairo-scaled-font.c:1381)
==26277==    by 0x40E7DD2: _cairo_xlib_surface_show_glyphs (cairo-xlib-surface.c:2810)
==26277==    by 0x40CF6D7: _cairo_surface_show_glyphs (cairo-surface.c:1830)
==26277==    by 0x40BC160: _cairo_gstate_show_glyphs (cairo-gstate.c:1504)
==26277==    by 0x40B5E26: _moz_cairo_show_text (cairo.c:2662)
==26277==    by 0x7D02E06: nsSVGGlyphFrame::LoopCharacters(_cairo*, nsAString_internal const&, nsSVGGlyphFrame::nsSVGCharacterPosition const*, void (*)(_cairo*, char const*)) (nsSVGGlyphFrame.cpp:203)
==26277==    by 0x7D0610B: nsSVGGlyphFrame::PaintSVG(nsISVGRendererCanvas*, nsRect*) (nsSVGGlyphFrame.cpp:286)
==26277==    by 0x7D25338: nsSVGUtils::PaintChildWithEffects(nsISVGRendererCanvas*, nsRect*, nsIFrame*) (nsSVGUtils.cpp:697)
==26277==    by 0x7CFA336: nsSVGDisplayContainerFrame::PaintSVG(nsISVGRendererCanvas*, nsRect*) (nsSVGContainerFrame.cpp:199)
==26277==    by 0x7D25338: nsSVGUtils::PaintChildWithEffects(nsISVGRendererCanvas*, nsRect*, nsIFrame*) (nsSVGUtils.cpp:697)
==26277==    by 0x7D138FE: nsSVGOuterSVGFrame::Paint(nsIRenderingContext&, nsRect const&, nsPoint) (nsSVGOuterSVGFrame.cpp:519)
==26277==    by 0x7D139E1: nsDisplaySVG::Paint(nsDisplayListBuilder*, nsIRenderingContext*, nsRect const&) (nsSVGOuterSVGFrame.cpp:419)
==26277==    by 0x76C8482: nsDisplayList::Paint(nsDisplayListBuilder*, nsIRenderingContext*, nsRect const&) const (nsDisplayList.cpp:298)
==26277==    by 0x76C8720: nsDisplayWrapList::Paint(nsDisplayListBuilder*, nsIRenderingContext*, nsRect const&) (nsDisplayList.cpp:706)
==26277==    by 0x76C9653: nsDisplayClip::Paint(nsDisplayListBuilder*, nsIRenderingContext*, nsRect const&) (nsDisplayList.cpp:938)
==26277==    by 0x76C8482: nsDisplayList::Paint(nsDisplayListBuilder*, nsIRenderingContext*, nsRect const&) const (nsDisplayList.cpp:298)
==26277==    by 0x76F1FA2: nsLayoutUtils::PaintFrame(nsIRenderingContext*, nsIFrame*, nsRegion const&, unsigned) (nsLayoutUtils.cpp:719)
==26277==    by 0x770348A: PresShell::Paint(nsIView*, nsIRenderingContext*, nsRegion const&) (nsPresShell.cpp:5652)
==26277==    by 0x7BA6F88: nsViewManager::RenderViews(nsView*, nsIRenderingContext&, nsRegion const&, nsIDrawingSurface*) (nsViewManager.cpp:815)
==26277==    by 0x7BA7CF9: nsViewManager::Refresh(nsView*, nsIRenderingContext*, nsIRegion*, unsigned) (nsViewManager.cpp:578)
==26277==    by 0x7BA83BC: nsViewManager::DispatchEvent(nsGUIEvent*, nsEventStatus*) (nsViewManager.cpp:1423)
==26277==    by 0x7B9D524: HandleEvent(nsGUIEvent*) (nsView.cpp:171)
==26277==    by 0x661400A: nsCommonWidget::DispatchEvent(nsGUIEvent*, nsEventStatus&) (nsCommonWidget.cpp:216)
==26277==    by 0x660749F: nsWindow::OnExposeEvent(_GtkWidget*, _GdkEventExpose*) (nsWindow.cpp:1635)
==26277==    by 0x66078F9: expose_event_cb(_GtkWidget*, _GdkEventExpose*) (nsWindow.cpp:4118)
==26277==    by 0x44C918B: (within /usr/lib/libgtk-x11-2.0.so.0.1000.3)
==26277==    by 0x48A42BA: g_closure_invoke (in /usr/lib/libgobject-2.0.so.0.1200.3)
==26277==    by 0x48B58ED: (within /usr/lib/libgobject-2.0.so.0.1200.3)
==26277==    by 0x48B6BC3: g_signal_emit_valist (in /usr/lib/libgobject-2.0.so.0.1200.3)
==26277==    by 0x48B6F9A: g_signal_emit (in /usr/lib/libgobject-2.0.so.0.1200.3)
==26277==    by 0x45E0610: (within /usr/lib/libgtk-x11-2.0.so.0.1000.3)
==26277==    by 0x44C3627: gtk_main_do_event (in /usr/lib/libgtk-x11-2.0.so.0.1000.3)
==26277==    by 0x4769884: (within /usr/lib/libgdk-x11-2.0.so.0.1000.3)
==26277==    by 0x4769ABB: gdk_window_process_all_updates (in /usr/lib/libgdk-x11-2.0.so.0.1000.3)
==26277==    by 0x4769B31: (within /usr/lib/libgdk-x11-2.0.so.0.1000.3)
==26277==    by 0x49033DF: (within /usr/lib/libglib-2.0.so.0.1200.3)
==26277==    by 0x49051B4: g_main_context_dispatch (in /usr/lib/libglib-2.0.so.0.1200.3)
==26277==    by 0x49081D1: (within /usr/lib/libglib-2.0.so.0.1200.3)
==26277==    by 0x490870B: g_main_context_iteration (in /usr/lib/libglib-2.0.so.0.1200.3)
==26277==    by 0x6611340: nsAppShell::ProcessNextNativeEvent(int) (nsAppShell.cpp:144)
...snip other threads seem sane...


valgrind on 2.0-latest:
** nsSVGTextFrame::DidSetStyleContext
SVG Viewport=(0?,0?,994,000061,846,000061)
SVG Viewbox=(1,000000,1,000000,48746356,000000,3,000000)
SVG Viewbox->Viewport xform [a c e] = [0,000020,   0, -0,000020]
                            [b d f] = [   0,  0,000020, 422,999969]
==2866== 
==2866== Invalid write of size 1
==2866==    at 0x4020173: memset (in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so)
==2866==    by 0x4CB728D: (within /usr/lib/libfreetype.so.6.3.10)
==2866==    by 0x4CB4F34: (within /usr/lib/libfreetype.so.6.3.10)
==2866==    by 0x4CB6202: (within /usr/lib/libfreetype.so.6.3.10)
==2866==    by 0x4C78D30: FT_Outline_Render (in /usr/lib/libfreetype.so.6.3.10)
==2866==    by 0x9420543: ???
==2866==    by 0x1D1C8: ???
==2866==  Address 0xC8F0F27 is not stack'd, malloc'd or (recently) free'd
==2866== 
==2866== Invalid write of size 1
==2866==    at 0x4020179: memset (in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so)
==2866==    by 0x4CB728D: (within /usr/lib/libfreetype.so.6.3.10)
==2866==    by 0x4CB4F34: (within /usr/lib/libfreetype.so.6.3.10)
==2866==    by 0x4CB6202: (within /usr/lib/libfreetype.so.6.3.10)
==2866==    by 0x4C78D30: FT_Outline_Render (in /usr/lib/libfreetype.so.6.3.10)
==2866==    by 0x9420543: ???
==2866==    by 0x1D1C8: ???
==2866==  Address 0xC8F0F29 is not stack'd, malloc'd or (recently) free'd

valgrind: m_mallocfree.c:194 (get_bszB_as_is): Assertion 'bszB_lo == bszB_hi' failed.
valgrind: Heap block lo/hi size mismatch: lo = 760177, hi = 2728567458.
Probably caused by overrunning/underrunning a heap block's bounds.

==2866==    at 0x380133A2: (within /usr/lib/valgrind/x86-linux/memcheck)
==2866==    by 0x380135DE: (within /usr/lib/valgrind/x86-linux/memcheck)
==2866==    by 0x3801AF3F: (within /usr/lib/valgrind/x86-linux/memcheck)
==2866==    by 0x3802DA19: (within /usr/lib/valgrind/x86-linux/memcheck)
==2866==    by 0x38001D0A: (within /usr/lib/valgrind/x86-linux/memcheck)
==2866==    by 0x3802E01B: (within /usr/lib/valgrind/x86-linux/memcheck)
==2866==    by 0x3802F498: (within /usr/lib/valgrind/x86-linux/memcheck)
==2866==    by 0x38043D79: (within /usr/lib/valgrind/x86-linux/memcheck)
sched status:
  running_tid=1

Thread 1: status = VgTs_Runnable
==2866==    at 0x401E65C: calloc (in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so)
==2866==    by 0x4770329: (within /usr/lib/libcairo.so.2.9.2)
==2866==    by 0x4772B44: (within /usr/lib/libcairo.so.2.9.2)
==2866==    by 0x4762D9B: (within /usr/lib/libcairo.so.2.9.2)
==2866==    by 0x4781F12: (within /usr/lib/libcairo.so.2.9.2)
==2866==    by 0x47665B9: (within /usr/lib/libcairo.so.2.9.2)
==2866==    by 0x475A39C: (within /usr/lib/libcairo.so.2.9.2)
==2866==    by 0x4755B2E: cairo_show_text (in /usr/lib/libcairo.so.2.9.2)
==2866==    by 0x74F5515: nsSVGGlyphFrame::PaintSVG(nsISVGRendererCanvas*, nsRect const&) (nsSVGGlyphFrame.cpp:462)
==2866==    by 0x751FFDF: nsSVGTextFrame::PaintSVG(nsISVGRendererCanvas*, nsRect const&) (nsSVGTextFrame.cpp:543)
==2866==    by 0x750D018: nsSVGOuterSVGFrame::Paint(nsPresContext*, nsIRenderingContext&, nsRect const&, nsFramePaintLayer, unsigned) (nsSVGOuterSVGFrame.cpp:849)
==2866==    by 0x6FFCB0A: nsContainerFrame::PaintChild(nsPresContext*, nsIRenderingContext&, nsRect const&, nsIFrame*, nsFramePaintLayer, unsigned) (nsContainerFrame.cpp:282)
==2866==    by 0x6FFA40A: nsContainerFrame::PaintChildren(nsPresContext*, nsIRenderingContext&, nsRect const&, nsFramePaintLayer, unsigned) (nsContainerFrame.cpp:227)
==2866==    by 0x7026D8E: nsHTMLContainerFrame::Paint(nsPresContext*, nsIRenderingContext&, nsRect const&, nsFramePaintLayer, unsigned) (nsHTMLContainerFrame.cpp:83)
==2866==    by 0x7027913: CanvasFrame::Paint(nsPresContext*, nsIRenderingContext&, nsRect const&, nsFramePaintLayer, unsigned) (nsHTMLFrame.cpp:383)
==2866==    by 0x6FBDB1D: PresShell::Paint(nsIView*, nsIRenderingContext&, nsRect const&) (nsPresShell.cpp:5866)
==2866==    by 0x73CB843: nsView::Paint(nsIRenderingContext&, nsRect const&, unsigned, int&) (nsView.cpp:314)
==2866==    by 0x73CFE43: nsViewManager::RenderDisplayListElement(DisplayListElement2*, nsIRenderingContext*) (nsViewManager.cpp:1458)
==2866==    by 0x73D7AA6: nsViewManager::RenderViews(nsView*, nsIRenderingContext&, nsRegion const&, nsIDrawingSurface*, nsVoidArray const&) (nsViewManager.cpp:1373)
==2866==    by 0x73D8DD0: nsViewManager::Refresh(nsView*, nsIRenderingContext*, nsIRegion*, unsigned) (nsViewManager.cpp:929)
==2866==    by 0x73D95A9: nsViewManager::DispatchEvent(nsGUIEvent*, nsEventStatus*) (nsViewManager.cpp:2045)
==2866==    by 0x73CB56C: HandleEvent(nsGUIEvent*) (nsView.cpp:171)
==2866==    by 0x5DEB870: nsCommonWidget::DispatchEvent(nsGUIEvent*, nsEventStatus&) (nsCommonWidget.cpp:219)
==2866==    by 0x5DE14D7: nsWindow::OnExposeEvent(_GtkWidget*, _GdkEventExpose*) (nsWindow.cpp:1433)
==2866==    by 0x5DE154D: expose_event_cb(_GtkWidget*, _GdkEventExpose*) (nsWindow.cpp:3729)
==2866==    by 0x43EC18B: (within /usr/lib/libgtk-x11-2.0.so.0.1000.3)
==2866==    by 0x47C42BA: g_closure_invoke (in /usr/lib/libgobject-2.0.so.0.1200.3)
==2866==    by 0x47D58ED: (within /usr/lib/libgobject-2.0.so.0.1200.3)
==2866==    by 0x47D6BC3: g_signal_emit_valist (in /usr/lib/libgobject-2.0.so.0.1200.3)
==2866==    by 0x47D6F9A: g_signal_emit (in /usr/lib/libgobject-2.0.so.0.1200.3)
==2866==    by 0x4503610: (within /usr/lib/libgtk-x11-2.0.so.0.1000.3)
==2866==    by 0x43E6627: gtk_main_do_event (in /usr/lib/libgtk-x11-2.0.so.0.1000.3)
==2866==    by 0x4671884: (within /usr/lib/libgdk-x11-2.0.so.0.1000.3)
==2866==    by 0x4671ABB: gdk_window_process_all_updates (in /usr/lib/libgdk-x11-2.0.so.0.1000.3)
==2866==    by 0x4671B31: (within /usr/lib/libgdk-x11-2.0.so.0.1000.3)
==2866==    by 0x48273DF: (within /usr/lib/libglib-2.0.so.0.1200.3)
==2866==    by 0x48291B4: g_main_context_dispatch (in /usr/lib/libglib-2.0.so.0.1200.3)
==2866==    by 0x482C1D1: (within /usr/lib/libglib-2.0.so.0.1200.3)
==2866==    by 0x482C543: g_main_loop_run (in /usr/lib/libglib-2.0.so.0.1200.3)
==2866==    by 0x43E699E: gtk_main (in /usr/lib/libgtk-x11-2.0.so.0.1000.3)
==2866==    by 0x5DE8E5F: nsAppShell::Run() (nsAppShell.cpp:139)
==2866==    by 0x5FB5531: nsAppStartup::Run() (nsAppStartup.cpp:151)
==2866==    by 0x8052483: XRE_main (nsAppRunner.cpp:2438)
==2866==    by 0x804B42B: main (nsBrowserApp.cpp:61)

My FF2 branch build does not crash. It dies in a cairo assert.

However, my build seems to be using the system cairo (1.2.4), not the Mozilla-tree cairo.
I suspect this is something specific to particular freetype/cairo versions and how they deal with oversized characters.
according to tests:

mandriva 2007 - both trunk and ff2: crash
kubuntu 6.10 - no crash, but X or KDE are quite lagged (not big memory usage)

suggest spamming upstream cairo/libfreetype.

doubt that the testcases may be minimized more.
I'm pretty sure this is a freetype bug where it crashes instead of returning an error. I would guess that this is an integer overflow that got fixed in the 2.2.1 release in May:
https://sourceforge.net/project/shownotes.php?release_id=416463&group_id=3157

Georgi, is that consistent with the freetype versions in your tests?
Attached patch cairo patchSplinter Review
I've this patch upstream to work around the cairo abort when Freetype returns an error --- it just caps the font size at 1000 pixels in each direction. I think we should probably take this on our branch to protect against bad Freetype packages. (Although it won't help if our tree-cairo gets overridden by a system cairo, as I seem to be seeing.)
Attachment #246437 - Flags: review?(vladimir)
(In reply to comment #16)
> I'm pretty sure this is a freetype bug where it crashes instead of returning an
> error. I would guess that this is an integer overflow that got fixed in the
> 2.2.1 release in May:
> https://sourceforge.net/project/shownotes.php?release_id=416463&group_id=3157
> 
> Georgi, is that consistent with the freetype versions in your tests?
> 

i am not sure 2.2.1 is safe:
mandriva 2007 (crashing)   : libfreetype6-2.2.1-4
ubuntu 6.0.6 (crashing)    : libfreetype6-2.1.10
ubuntu 6.10 (non crashing) : libfreetype6-2.2.1-5

fuzzing the testcase when non crashing doesn't crash, but enter *very big* loops (about 10 minutes and still running).




mac ppc is safe from this.

about the cairo patch:
+#define MAX_FONT_SIZE 1000

+        double x_scale = sf.x_scale;
+        double y_scale = sf.y_scale;
+        if (x_scale > MAX_FONT_SIZE) {
+            x_scale = MAX_FONT_SIZE;

not sure if this is effective for *negative* x_scale.
Comment on attachment 246437 [details] [diff] [review]
cairo patch

The way sf.[xy]_scale is computed (through _cairo_matrix_compute_scale_factors), they can't be negative as far as I can see.
Attachment #246437 - Flags: review?(vladimir) → review+
Whiteboard: [sg:critical?] fixed on trunk, dupe? → [sg:critical?] need approval, branch landing (fixed on trunk, dupe?)
Checked into trunk.
Status: NEW → RESOLVED
Closed: 18 years ago
Resolution: --- → FIXED
Comment on attachment 246437 [details] [diff] [review]
cairo patch

okay, this can go on branches now. I think it's pretty darn safe!
Attachment #246437 - Flags: approval1.8.1.1?
Attachment #246437 - Flags: approval1.8.0.9?
Comment on attachment 246437 [details] [diff] [review]
cairo patch

approved for 1.8/1.8.0 branches, a=dveditz for drivers
Attachment #246437 - Flags: approval1.8.1.1?
Attachment #246437 - Flags: approval1.8.1.1+
Attachment #246437 - Flags: approval1.8.0.9?
Attachment #246437 - Flags: approval1.8.0.9+
Whiteboard: [sg:critical?] need approval, branch landing (fixed on trunk, dupe?) → [sg:critical?] needs branch landing
verified fixed 1.8.0.9, 1.8.1.1, 1.9 windows/linux/macppc
no crashes on either attached testcase.
Status: RESOLVED → VERIFIED
Group: security
Whiteboard: [sg:critical?] needs branch landing → [sg:critical?]
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: