Bug 700301

Summary: infinite loop in function svg_dev_end_tile in source/fitz/svg-device.c
Product: MuPDF Reporter: kuaicar87
Component: svg outputAssignee: Robin Watts <robin.watts>
Status: RESOLVED FIXED QA Contact: Bug traffic <tech>
Severity: normal    
Priority: P4 CC: mjg
Version: master   
Hardware: PC   
OS: Linux   
Customer: Word Size: ---
Attachments: the POC to trigger the bug

Description kuaicar87 2018-11-30 03:08:49 UTC
Created attachment 16426 [details]
the POC to trigger the bug

When I tried to convert a pdf file to svg file, there is an infite loop in svg_dev_end_tile in source/fitz/svg-device.c. 

static void
svg_dev_end_tile(fz_context *ctx, fz_device *dev)

for (x = 0; x > -w; x -= t->step.x)
		for (y = 0; y > -h; y -= t->step.y)
			fz_write_printf(ctx, out, "<use x=\"%g\" y=\"%g\" xlink:href=\"#pac%d\"/>\n", x, y, t->pattern);

gef➤  p t.step
$11 = {
  x = 0, 
  y = 0
because the values of t->step.x and t->step.y always are zero, so the program can be stuck in infinite loop state.
Comment 1 kuaicar87 2018-11-30 03:10:23 UTC
This bug is reported by fish@360TeamSeri0us, please send email to teamSeri0us360@gmail.com if you have some quetions.
Comment 2 M.J.G. 2019-05-13 13:00:59 UTC
I can confirm this bug is still present in 1.15.0.
Comment 3 Tor Andersson 2019-05-15 17:05:28 UTC
commit 754ac68f119e0c25cd33c5d652d8aabd533a9fb3
Author: Robin Watts <Robin.Watts@artifex.com>
Date:   Mon May 13 13:28:57 2019 +0100

    Bug 700301: Fix potential infinite loop in svg output device.
    The POC in the bug no longer triggers the problem, but potentially
    the problem is there all the same.
    Spot an attempt to define a pattern with X or Y height of 0, and
    cope with it. We print a warning, and reset the X or Y step to 1.
Comment 4 M.J.G. 2019-05-16 13:16:21 UTC
I don't want to be extra picky, but I'm not sure this fix is complete:

Since we're dealing with floats here, xstep and ystep may very well be != 0 (say, only in the lowest digit) but as soon as we add up the steps often enough (say, 10^d times, d the representable digits) we will have x == x - xstep, i.e. the same problem.

Thus, an evil attacker can still trigger the bug with specifically chosen steps.

I see two possible solutions:

- impose a larger lower bound on the step size (then just >0) in begin_tile()

- check for x-xstep != xstep in end_tile(); might be too expensive