~jconti/ubuntu/oneiric/webkit/fix_doc_path

« back to all changes in this revision

Viewing changes to WebCore/dom/NodeIterator.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
 
 * This file is part of the DOM implementation for KDE.
3
 
 *
 
1
/*
4
2
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
5
3
 * Copyright (C) 2000 Frederik Holljen (frederik.holljen@hig.no)
6
4
 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
7
5
 * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
8
 
 * Copyright (C) 2004 Apple Computer, Inc.
 
6
 * Copyright (C) 2004, 2008 Apple Inc. All rights reserved.
9
7
 *
10
8
 * This library is free software; you can redistribute it and/or
11
9
 * modify it under the terms of the GNU Library General Public
19
17
 *
20
18
 * You should have received a copy of the GNU Library General Public License
21
19
 * along with this library; see the file COPYING.LIB.  If not, write to
22
 
 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23
 
 * Boston, MA 02111-1307, USA.
 
20
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 
21
 * Boston, MA 02110-1301, USA.
24
22
 *
25
23
 */
26
24
 
31
29
#include "ExceptionCode.h"
32
30
#include "NodeFilter.h"
33
31
 
 
32
using namespace KJS;
 
33
 
34
34
namespace WebCore {
35
35
 
36
 
NodeIterator::NodeIterator(Node* rootNode, unsigned whatToShow, PassRefPtr<NodeFilter> filter, bool expandEntityReferences)
 
36
NodeIterator::NodePointer::NodePointer()
 
37
{
 
38
}
 
39
 
 
40
NodeIterator::NodePointer::NodePointer(PassRefPtr<Node> n, bool b)
 
41
    : node(n)
 
42
    , isPointerBeforeNode(b)
 
43
{
 
44
}
 
45
 
 
46
void NodeIterator::NodePointer::clear()
 
47
{
 
48
    node.clear();
 
49
}
 
50
 
 
51
bool NodeIterator::NodePointer::moveToNext(Node* root)
 
52
{
 
53
    if (!node)
 
54
        return false;
 
55
    if (isPointerBeforeNode) {
 
56
        isPointerBeforeNode = false;
 
57
        return true;
 
58
    }
 
59
    node = node->traverseNextNode(root);
 
60
    return node;
 
61
}
 
62
 
 
63
bool NodeIterator::NodePointer::moveToPrevious(Node* root)
 
64
{
 
65
    if (!node)
 
66
        return false;
 
67
    if (!isPointerBeforeNode) {
 
68
        isPointerBeforeNode = true;
 
69
        return true;
 
70
    }
 
71
    node = node->traversePreviousNode(root);
 
72
    return node;
 
73
}
 
74
 
 
75
NodeIterator::NodeIterator(PassRefPtr<Node> rootNode, unsigned whatToShow, PassRefPtr<NodeFilter> filter, bool expandEntityReferences)
37
76
    : Traversal(rootNode, whatToShow, filter, expandEntityReferences)
38
 
    , m_beforeReferenceNode(true)
 
77
    , m_referenceNode(root(), true)
39
78
    , m_detached(false)
40
 
    , m_doc(rootNode ? rootNode->document() : 0)
41
79
{
42
 
    if (document())
43
 
        document()->attachNodeIterator(this);
 
80
    root()->document()->attachNodeIterator(this);
44
81
}
45
82
 
46
83
NodeIterator::~NodeIterator()
47
84
{
48
 
    if (document())
49
 
        document()->detachNodeIterator(this);
50
 
}
51
 
 
52
 
Node* NodeIterator::findNextNode(Node* node) const
53
 
{
54
 
    while ((node = node->traverseNextNode(root()))) {
55
 
        // NodeIterators treat the DOM tree as a flat list of nodes.
56
 
        // In other words, FILTER_REJECT does not pass over descendants
57
 
        // of the rejected node. Hence, FILTER_REJECT is the same as FILTER_SKIP.
58
 
        if (acceptNode(node) == NodeFilter::FILTER_ACCEPT)
59
 
            break;
60
 
    }
61
 
    return node;
62
 
}
63
 
 
64
 
Node* NodeIterator::nextNode(ExceptionCode& ec)
65
 
{
66
 
    if (detached()) {
67
 
        ec = INVALID_STATE_ERR;
68
 
        return 0;
69
 
    }
70
 
 
71
 
    Node* node = referenceNode() ? referenceNode() : root();
72
 
    if (!pointerBeforeReferenceNode() || acceptNode(node) != NodeFilter::FILTER_ACCEPT)
73
 
        node = findNextNode(node);
74
 
    if (node)
75
 
        setReferenceNode(node);
76
 
    setPointerBeforeReferenceNode(false);
77
 
    return node;
78
 
}
79
 
 
80
 
Node* NodeIterator::findPreviousNode(Node* node) const
81
 
{
82
 
    while ((node = node->traversePreviousNode(root()))) {
83
 
        // NodeIterators treat the DOM tree as a flat list of nodes.
84
 
        // In other words, FILTER_REJECT does not pass over descendants
85
 
        // of the rejected node. Hence, FILTER_REJECT is the same as FILTER_SKIP.
86
 
        if (acceptNode(node) == NodeFilter::FILTER_ACCEPT)
87
 
            break;
88
 
    }
89
 
    return node;
90
 
}
91
 
 
92
 
Node* NodeIterator::previousNode(ExceptionCode&)
93
 
{
94
 
    Node* node = referenceNode() ? referenceNode() : root();
95
 
    if (pointerBeforeReferenceNode() || acceptNode(node) != NodeFilter::FILTER_ACCEPT)
96
 
        node = findPreviousNode(node);
97
 
    if (node)
98
 
        setReferenceNode(node);
99
 
    setPointerBeforeReferenceNode();
100
 
    return node;
 
85
    root()->document()->detachNodeIterator(this);
 
86
}
 
87
 
 
88
PassRefPtr<Node> NodeIterator::nextNode(ExceptionCode& ec, JSValue*& exception)
 
89
{
 
90
    if (m_detached) {
 
91
        ec = INVALID_STATE_ERR;
 
92
        return 0;
 
93
    }
 
94
 
 
95
    RefPtr<Node> result;
 
96
 
 
97
    m_candidateNode = m_referenceNode;
 
98
    while (m_candidateNode.moveToNext(root())) {
 
99
        // NodeIterators treat the DOM tree as a flat list of nodes.
 
100
        // In other words, FILTER_REJECT does not pass over descendants
 
101
        // of the rejected node. Hence, FILTER_REJECT is the same as FILTER_SKIP.
 
102
        exception = 0;
 
103
        RefPtr<Node> provisionalResult = m_candidateNode.node;
 
104
        bool nodeWasAccepted = acceptNode(provisionalResult.get(), exception) == NodeFilter::FILTER_ACCEPT;
 
105
        if (exception)
 
106
            break;
 
107
        if (nodeWasAccepted) {
 
108
            m_referenceNode = m_candidateNode;
 
109
            result = provisionalResult.release();
 
110
            break;
 
111
        }
 
112
    }
 
113
 
 
114
    m_candidateNode.clear();
 
115
    return result.release();
 
116
}
 
117
 
 
118
PassRefPtr<Node> NodeIterator::previousNode(ExceptionCode& ec, JSValue*& exception)
 
119
{
 
120
    if (m_detached) {
 
121
        ec = INVALID_STATE_ERR;
 
122
        return 0;
 
123
    }
 
124
 
 
125
    RefPtr<Node> result;
 
126
 
 
127
    m_candidateNode = m_referenceNode;
 
128
    while (m_candidateNode.moveToPrevious(root())) {
 
129
        // NodeIterators treat the DOM tree as a flat list of nodes.
 
130
        // In other words, FILTER_REJECT does not pass over descendants
 
131
        // of the rejected node. Hence, FILTER_REJECT is the same as FILTER_SKIP.
 
132
        exception = 0;
 
133
        RefPtr<Node> provisionalResult = m_candidateNode.node;
 
134
        bool nodeWasAccepted = acceptNode(provisionalResult.get(), exception) == NodeFilter::FILTER_ACCEPT;
 
135
        if (exception)
 
136
            break;
 
137
        if (nodeWasAccepted) {
 
138
            m_referenceNode = m_candidateNode;
 
139
            result = provisionalResult.release();
 
140
            break;
 
141
        }
 
142
    }
 
143
 
 
144
    m_candidateNode.clear();
 
145
    return result.release();
101
146
}
102
147
 
103
148
void NodeIterator::detach()
104
149
{
105
 
    if (!detached() && document())
106
 
        document()->detachNodeIterator(this);
107
 
    setDetached();
108
 
}
109
 
 
110
 
void NodeIterator::setReferenceNode(Node* node)
111
 
{
112
 
    m_referenceNode = node;
113
 
}
114
 
 
115
 
void NodeIterator::notifyBeforeNodeRemoval(Node* removedNode)
116
 
{
 
150
    root()->document()->detachNodeIterator(this);
 
151
    m_detached = true;
 
152
    m_referenceNode.node.clear();
 
153
}
 
154
 
 
155
void NodeIterator::nodeWillBeRemoved(Node* removedNode)
 
156
{
 
157
    updateForNodeRemoval(removedNode, m_candidateNode);
 
158
    updateForNodeRemoval(removedNode, m_referenceNode);
 
159
}
 
160
 
 
161
void NodeIterator::updateForNodeRemoval(Node* removedNode, NodePointer& referenceNode) const
 
162
{
 
163
    ASSERT(!m_detached);
 
164
    ASSERT(removedNode);
 
165
    ASSERT(root()->document() == removedNode->document());
 
166
 
117
167
    // Iterator is not affected if the removed node is the reference node and is the root.
118
168
    // or if removed node is not the reference node, or the ancestor of the reference node.
119
 
    if (!removedNode || removedNode == root() || !removedNode->isDescendantOf(root()))
 
169
    if (!removedNode->isDescendantOf(root()))
120
170
        return;
121
 
    bool willRemoveReferenceNode = removedNode == referenceNode();
122
 
    bool willRemoveReferenceNodeAncestor = referenceNode() && referenceNode()->isDescendantOf(removedNode);
 
171
    bool willRemoveReferenceNode = removedNode == referenceNode.node;
 
172
    bool willRemoveReferenceNodeAncestor = referenceNode.node && referenceNode.node->isDescendantOf(removedNode);
123
173
    if (!willRemoveReferenceNode && !willRemoveReferenceNodeAncestor)
124
174
        return;
125
175
 
126
 
    if (pointerBeforeReferenceNode()) {
127
 
        Node* node = findNextNode(removedNode);
 
176
    if (referenceNode.isPointerBeforeNode) {
 
177
        Node* node = removedNode->traverseNextNode(root());
128
178
        if (node) {
129
179
            // Move out from under the node being removed if the reference node is
130
180
            // a descendant of the node being removed.
131
181
            if (willRemoveReferenceNodeAncestor) {
132
182
                while (node && node->isDescendantOf(removedNode))
133
 
                    node = findNextNode(node);
 
183
                    node = node->traverseNextNode(root());
134
184
            }
135
185
            if (node)
136
 
                setReferenceNode(node);
 
186
                referenceNode.node = node;
137
187
        } else {
138
 
            node = findPreviousNode(removedNode);
 
188
            node = removedNode->traversePreviousNode(root());
139
189
            if (node) {
140
190
                // Move out from under the node being removed if the reference node is
141
191
                // a descendant of the node being removed.
142
192
                if (willRemoveReferenceNodeAncestor) {
143
193
                    while (node && node->isDescendantOf(removedNode))
144
 
                        node = findPreviousNode(node);
 
194
                        node = node->traversePreviousNode(root());
145
195
                }
146
196
                if (node) {
147
197
                    // Removing last node.
148
198
                    // Need to move the pointer after the node preceding the 
149
199
                    // new reference node.
150
 
                    setReferenceNode(node);
151
 
                    setPointerBeforeReferenceNode(false);
 
200
                    referenceNode.node = node;
 
201
                    referenceNode.isPointerBeforeNode = false;
152
202
                }
153
203
            }
154
204
        }
155
205
    } else {
156
 
        Node* node = findPreviousNode(removedNode);
 
206
        Node* node = removedNode->traversePreviousNode(root());
157
207
        if (node) {
158
208
            // Move out from under the node being removed if the reference node is
159
209
            // a descendant of the node being removed.
160
210
            if (willRemoveReferenceNodeAncestor) {
161
211
                while (node && node->isDescendantOf(removedNode))
162
 
                    node = findPreviousNode(node);
 
212
                    node = node->traversePreviousNode(root());
163
213
            }
164
214
            if (node)
165
 
                setReferenceNode(node);
 
215
                referenceNode.node = node;
166
216
        } else {
167
 
            node = findNextNode(removedNode);
 
217
            node = removedNode->traverseNextNode(root());
168
218
            // Move out from under the node being removed if the reference node is
169
219
            // a descendant of the node being removed.
170
220
            if (willRemoveReferenceNodeAncestor) {
171
221
                while (node && node->isDescendantOf(removedNode))
172
 
                    node = findPreviousNode(node);
 
222
                    node = node->traversePreviousNode(root());
173
223
            }
174
224
            if (node)
175
 
                setReferenceNode(node);
 
225
                referenceNode.node = node;
176
226
        }
177
227
    }
178
228
}