~jconti/ubuntu/oneiric/webkit/fix_doc_path

« back to all changes in this revision

Viewing changes to WebCore/svg/SVGPathSegList.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Mike Hommey
  • Date: 2008-09-27 08:57:48 UTC
  • mfrom: (3.1.6 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080927085748-yhzld00w0rekp961
Tags: 1.0.1-4
WebCore/dom/Document.*, WebCore/loader/DocLoader.*: Avoid DoS via
crafted CSS import statements. Fixes: CVE-2008-3632. Closes: #499771.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
 
3
                  2004, 2005 Rob Buis <buis@kde.org>
 
4
    Copyright (C) 2007 Eric Seidel <eric@webkit.org>
 
5
 
 
6
    This file is part of the WebKit project
 
7
 
 
8
    This library is free software; you can redistribute it and/or
 
9
    modify it under the terms of the GNU Library General Public
 
10
    License as published by the Free Software Foundation; either
 
11
    version 2 of the License, or (at your option) any later version.
 
12
 
 
13
    This library is distributed in the hope that it will be useful,
 
14
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
16
    Library General Public License for more details.
 
17
 
 
18
    You should have received a copy of the GNU Library General Public License
 
19
    along with this library; see the file COPYING.LIB.  If not, write to
 
20
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 
21
    Boston, MA 02110-1301, USA.
 
22
*/
 
23
 
 
24
#include "config.h"
 
25
 
 
26
#if ENABLE(SVG)
 
27
#include "SVGPathSegList.h"
 
28
 
 
29
#include "FloatPoint.h"
 
30
#include "Path.h"
 
31
#include "PathTraversalState.h"
 
32
#include "SVGPathSegArc.h"
 
33
#include "SVGPathSegClosePath.h"
 
34
#include "SVGPathSegMoveto.h"
 
35
#include "SVGPathSegLineto.h"
 
36
#include "SVGPathSegLinetoHorizontal.h"
 
37
#include "SVGPathSegLinetoVertical.h"
 
38
#include "SVGPathSegCurvetoCubic.h"
 
39
#include "SVGPathSegCurvetoCubicSmooth.h"
 
40
#include "SVGPathSegCurvetoQuadratic.h"
 
41
#include "SVGPathSegCurvetoQuadraticSmooth.h"
 
42
 
 
43
namespace WebCore {
 
44
 
 
45
SVGPathSegList::SVGPathSegList(const QualifiedName& attributeName)
 
46
    : SVGList<RefPtr<SVGPathSeg> >(attributeName)
 
47
{
 
48
}
 
49
 
 
50
SVGPathSegList::~SVGPathSegList()
 
51
{
 
52
}
 
53
 
 
54
unsigned SVGPathSegList::getPathSegAtLength(double)
 
55
{
 
56
    // FIXME : to be useful this will need to support non-normalized SVGPathSegLists
 
57
    ExceptionCode ec = 0;
 
58
    int len = numberOfItems();
 
59
    // FIXME: Eventually this will likely move to a "path applier"-like model, until then PathTraversalState is less useful as we could just use locals
 
60
    PathTraversalState traversalState(PathTraversalState::TraversalSegmentAtLength);
 
61
    for (int i = 0; i < len; ++i) {
 
62
        SVGPathSeg* segment = getItem(i, ec).get();
 
63
        float segmentLength = 0;
 
64
        switch (segment->pathSegType()) {
 
65
        case SVGPathSeg::PATHSEG_MOVETO_ABS:
 
66
        {
 
67
            SVGPathSegMovetoAbs* moveTo = static_cast<SVGPathSegMovetoAbs*>(segment);
 
68
            segmentLength = traversalState.moveTo(FloatPoint(moveTo->x(), moveTo->y()));
 
69
            break;
 
70
        }
 
71
        case SVGPathSeg::PATHSEG_LINETO_ABS:
 
72
        {
 
73
            SVGPathSegLinetoAbs* lineTo = static_cast<SVGPathSegLinetoAbs*>(segment);
 
74
            segmentLength = traversalState.lineTo(FloatPoint(lineTo->x(), lineTo->y()));
 
75
            break;
 
76
        }
 
77
        case SVGPathSeg::PATHSEG_CURVETO_CUBIC_ABS:
 
78
        {
 
79
            SVGPathSegCurvetoCubicAbs* curveTo = static_cast<SVGPathSegCurvetoCubicAbs*>(segment);
 
80
            segmentLength = traversalState.cubicBezierTo(FloatPoint(curveTo->x1(), curveTo->y1()),
 
81
                                      FloatPoint(curveTo->x2(), curveTo->y2()),
 
82
                                      FloatPoint(curveTo->x(), curveTo->y()));
 
83
            break;
 
84
        }
 
85
        case SVGPathSeg::PATHSEG_CLOSEPATH:
 
86
            segmentLength = traversalState.closeSubpath();
 
87
            break;
 
88
        default:
 
89
            ASSERT(false); // FIXME: This only works with normalized/processed path data.
 
90
            break;
 
91
        }
 
92
        traversalState.m_totalLength += segmentLength;
 
93
        if ((traversalState.m_action == PathTraversalState::TraversalSegmentAtLength)
 
94
            && (traversalState.m_totalLength > traversalState.m_desiredLength)) {
 
95
            return traversalState.m_segmentIndex;
 
96
        }
 
97
        traversalState.m_segmentIndex++;
 
98
    }
 
99
    
 
100
    return 0; // The SVG spec is unclear as to what to return when the distance is not on the path    
 
101
}
 
102
 
 
103
Path SVGPathSegList::toPathData()
 
104
{
 
105
    // FIXME : This should also support non-normalized PathSegLists
 
106
    Path pathData;
 
107
    ExceptionCode ec = 0;
 
108
    int len = numberOfItems();
 
109
    for (int i = 0; i < len; ++i) {
 
110
        SVGPathSeg* segment = getItem(i, ec).get();;
 
111
        switch (segment->pathSegType())
 
112
        {
 
113
            case SVGPathSeg::PATHSEG_MOVETO_ABS:
 
114
            {
 
115
                SVGPathSegMovetoAbs* moveTo = static_cast<SVGPathSegMovetoAbs*>(segment);
 
116
                pathData.moveTo(FloatPoint(moveTo->x(), moveTo->y()));
 
117
                break;
 
118
            }
 
119
            case SVGPathSeg::PATHSEG_LINETO_ABS:
 
120
            {
 
121
                SVGPathSegLinetoAbs* lineTo = static_cast<SVGPathSegLinetoAbs*>(segment);
 
122
                pathData.addLineTo(FloatPoint(lineTo->x(), lineTo->y()));
 
123
                break;
 
124
            }
 
125
            case SVGPathSeg::PATHSEG_CURVETO_CUBIC_ABS:
 
126
            {
 
127
                SVGPathSegCurvetoCubicAbs* curveTo = static_cast<SVGPathSegCurvetoCubicAbs*>(segment);
 
128
                pathData.addBezierCurveTo(FloatPoint(curveTo->x1(), curveTo->y1()),
 
129
                                          FloatPoint(curveTo->x2(), curveTo->y2()),
 
130
                                          FloatPoint(curveTo->x(), curveTo->y()));
 
131
                break;
 
132
            }
 
133
            case SVGPathSeg::PATHSEG_CLOSEPATH:
 
134
                pathData.closeSubpath();
 
135
                break;
 
136
            default:
 
137
                ASSERT(false); // FIXME: This only works with normalized/processed path data.
 
138
                break;
 
139
        }
 
140
    }
 
141
    
 
142
    return pathData;
 
143
}
 
144
    
 
145
static inline float blendFunc(float from, float to, float progress)
 
146
{
 
147
    return (to - from) * progress + from;
 
148
}
 
149
    
 
150
#define BLENDPATHSEG1(class, attr1) \
 
151
    class::create(blendFunc(static_cast<class*>(from)->attr1(), static_cast<class*>(to)->attr1(), progress))
 
152
    
 
153
#define BLENDPATHSEG2(class, attr1, attr2) \
 
154
    class::create(blendFunc(static_cast<class*>(from)->attr1(), static_cast<class*>(to)->attr1(), progress), \
 
155
                    blendFunc(static_cast<class*>(from)->attr2(), static_cast<class*>(to)->attr2(), progress))
 
156
    
 
157
#define BLENDPATHSEG4(class, attr1, attr2, attr3, attr4) \
 
158
    class::create(blendFunc(static_cast<class*>(from)->attr1(), static_cast<class*>(to)->attr1(), progress), \
 
159
                blendFunc(static_cast<class*>(from)->attr2(), static_cast<class*>(to)->attr2(), progress), \
 
160
                blendFunc(static_cast<class*>(from)->attr3(), static_cast<class*>(to)->attr3(), progress), \
 
161
                blendFunc(static_cast<class*>(from)->attr4(), static_cast<class*>(to)->attr4(), progress))
 
162
    
 
163
#define BLENDPATHSEG6(class, attr1, attr2, attr3, attr4, attr5, attr6) \
 
164
    class::create(blendFunc(static_cast<class*>(from)->attr1(), static_cast<class*>(to)->attr1(), progress), \
 
165
                blendFunc(static_cast<class*>(from)->attr2(), static_cast<class*>(to)->attr2(), progress), \
 
166
                blendFunc(static_cast<class*>(from)->attr3(), static_cast<class*>(to)->attr3(), progress), \
 
167
                blendFunc(static_cast<class*>(from)->attr4(), static_cast<class*>(to)->attr4(), progress), \
 
168
                blendFunc(static_cast<class*>(from)->attr5(), static_cast<class*>(to)->attr5(), progress), \
 
169
                blendFunc(static_cast<class*>(from)->attr6(), static_cast<class*>(to)->attr6(), progress))
 
170
 
 
171
#define BLENDPATHSEG7(class, attr1, attr2, attr3, attr4, attr5, bool1, bool2) \
 
172
    class::create(blendFunc(static_cast<class*>(from)->attr1(), static_cast<class*>(to)->attr1(), progress), \
 
173
                blendFunc(static_cast<class*>(from)->attr2(), static_cast<class*>(to)->attr2(), progress), \
 
174
                blendFunc(static_cast<class*>(from)->attr3(), static_cast<class*>(to)->attr3(), progress), \
 
175
                blendFunc(static_cast<class*>(from)->attr4(), static_cast<class*>(to)->attr4(), progress), \
 
176
                blendFunc(static_cast<class*>(from)->attr5(), static_cast<class*>(to)->attr5(), progress), \
 
177
                static_cast<bool>(blendFunc(static_cast<class*>(from)->bool1(), static_cast<class*>(to)->bool1(), progress)), \
 
178
                static_cast<bool>(blendFunc(static_cast<class*>(from)->bool2(), static_cast<class*>(to)->bool2(), progress)))
 
179
 
 
180
PassRefPtr<SVGPathSegList> SVGPathSegList::createAnimated(const SVGPathSegList* fromList, const SVGPathSegList* toList, float progress)
 
181
{
 
182
    unsigned itemCount = fromList->numberOfItems();
 
183
    if (!itemCount || itemCount != toList->numberOfItems())
 
184
        return 0;
 
185
    RefPtr<SVGPathSegList> result = create(fromList->associatedAttributeName());
 
186
    ExceptionCode ec;
 
187
    for (unsigned n = 0; n < itemCount; ++n) {
 
188
        SVGPathSeg* from = fromList->getItem(n, ec).get();
 
189
        SVGPathSeg* to = toList->getItem(n, ec).get();
 
190
        if (from->pathSegType() == SVGPathSeg::PATHSEG_UNKNOWN || from->pathSegType() != to->pathSegType())
 
191
            return 0;
 
192
        RefPtr<SVGPathSeg> segment = 0;
 
193
        switch (static_cast<SVGPathSeg::SVGPathSegType>(from->pathSegType())) {
 
194
        case SVGPathSeg::PATHSEG_CLOSEPATH:
 
195
            segment = SVGPathSegClosePath::create();
 
196
            break;
 
197
        case SVGPathSeg::PATHSEG_LINETO_HORIZONTAL_ABS:
 
198
            segment = BLENDPATHSEG1(SVGPathSegLinetoHorizontalAbs, x);
 
199
            break;
 
200
        case SVGPathSeg::PATHSEG_LINETO_HORIZONTAL_REL:
 
201
            segment = BLENDPATHSEG1(SVGPathSegLinetoHorizontalRel, x);
 
202
            break;   
 
203
        case SVGPathSeg::PATHSEG_LINETO_VERTICAL_ABS:
 
204
            segment = BLENDPATHSEG1(SVGPathSegLinetoVerticalAbs, y);
 
205
            break;
 
206
        case SVGPathSeg::PATHSEG_LINETO_VERTICAL_REL:
 
207
            segment = BLENDPATHSEG1(SVGPathSegLinetoVerticalRel, y);
 
208
            break;        
 
209
        case SVGPathSeg::PATHSEG_MOVETO_ABS:
 
210
            segment = BLENDPATHSEG2(SVGPathSegMovetoAbs, x, y);
 
211
            break;
 
212
        case SVGPathSeg::PATHSEG_MOVETO_REL:
 
213
            segment = BLENDPATHSEG2(SVGPathSegMovetoRel, x, y);
 
214
            break;
 
215
        case SVGPathSeg::PATHSEG_LINETO_ABS:
 
216
            segment = BLENDPATHSEG2(SVGPathSegLinetoAbs, x, y);
 
217
            break;
 
218
        case SVGPathSeg::PATHSEG_LINETO_REL:
 
219
            segment = BLENDPATHSEG2(SVGPathSegLinetoRel, x, y);
 
220
            break;
 
221
        case SVGPathSeg::PATHSEG_CURVETO_CUBIC_ABS:
 
222
            segment = BLENDPATHSEG6(SVGPathSegCurvetoCubicAbs, x, y, x1, y1, x2, y2);
 
223
            break;
 
224
        case SVGPathSeg::PATHSEG_CURVETO_CUBIC_REL:
 
225
            segment = BLENDPATHSEG6(SVGPathSegCurvetoCubicRel, x, y, x1, y1, x2, y2);
 
226
            break;
 
227
        case SVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:
 
228
            segment = BLENDPATHSEG4(SVGPathSegCurvetoCubicSmoothAbs, x, y, x2, y2);
 
229
            break;
 
230
        case SVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_REL:
 
231
            segment = BLENDPATHSEG4(SVGPathSegCurvetoCubicSmoothRel, x, y, x2, y2);
 
232
            break;
 
233
        case SVGPathSeg::PATHSEG_CURVETO_QUADRATIC_ABS:
 
234
            segment = BLENDPATHSEG4(SVGPathSegCurvetoQuadraticAbs, x, y, x1, y1);
 
235
            break;
 
236
        case SVGPathSeg::PATHSEG_CURVETO_QUADRATIC_REL:
 
237
            segment = BLENDPATHSEG4(SVGPathSegCurvetoQuadraticRel, x, y, x1, y1);
 
238
            break;
 
239
        case SVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:
 
240
            segment = BLENDPATHSEG2(SVGPathSegCurvetoQuadraticSmoothAbs, x, y);
 
241
            break;
 
242
        case SVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:
 
243
            segment = BLENDPATHSEG2(SVGPathSegCurvetoQuadraticSmoothRel, x, y);
 
244
            break;
 
245
        case SVGPathSeg::PATHSEG_ARC_ABS:
 
246
            segment = BLENDPATHSEG7(SVGPathSegArcAbs, x, y, r1, r2, angle, largeArcFlag, sweepFlag);
 
247
            break;
 
248
        case SVGPathSeg::PATHSEG_ARC_REL:
 
249
            segment = BLENDPATHSEG7(SVGPathSegArcRel, x, y, r1, r2, angle, largeArcFlag, sweepFlag);
 
250
            break;
 
251
        case SVGPathSeg::PATHSEG_UNKNOWN:
 
252
            ASSERT_NOT_REACHED();
 
253
        }
 
254
        result->appendItem(segment, ec);
 
255
    }
 
256
    return result.release();
 
257
}
 
258
 
 
259
}
 
260
 
 
261
#endif // ENABLE(SVG)