Skip to content

Commit 5c841b1

Browse files
[FIX] XQuery, db:store: out of bounds. Closes BaseXdb#2100
1 parent e1c5e9a commit 5c841b1

File tree

5 files changed

+44
-21
lines changed

5 files changed

+44
-21
lines changed

basex-core/src/main/java/org/basex/query/up/ContextModifier.java

+1-3
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,7 @@ final synchronized void apply(final QueryContext qc) throws QueryException {
129129
}
130130

131131
// apply remaining updates based on database names
132-
for(final NameUpdates up : nameUpdates.values()) {
133-
up.apply(false);
134-
}
132+
for(final NameUpdates up : nameUpdates.values()) up.apply(false);
135133
}
136134

137135
/**

basex-core/src/main/java/org/basex/query/up/DataUpdates.java

+28-16
Original file line numberDiff line numberDiff line change
@@ -158,17 +158,16 @@ Data data() {
158158
* @throws QueryException query exception
159159
*/
160160
void apply(final QueryContext qc) throws QueryException {
161-
// execute database updates
161+
// apply initial database operations
162+
Collections.sort(dbUpdates);
163+
applyDbUpdates(true);
164+
165+
// execute updates within databases
162166
auc.execute(true);
163167
auc = null;
164168

165-
// execute database operations
166-
Collections.sort(dbUpdates);
167-
final int sz = dbUpdates.size();
168-
for(int i = 0; i < sz; i++) {
169-
dbUpdates.get(i).apply();
170-
dbUpdates.set(i, null);
171-
}
169+
// apply remaining database operations
170+
applyDbUpdates(false);
172171

173172
// execute fn:put operations
174173
for(final Put put : puts.values()) put.apply();
@@ -198,6 +197,23 @@ void apply(final QueryContext qc) throws QueryException {
198197
}
199198
}
200199

200+
/**
201+
* Applies all database operations.
202+
* @param before run updates specified before or after node updates
203+
* @throws QueryException query exception
204+
*/
205+
private void applyDbUpdates(final boolean before) throws QueryException {
206+
final int pos = UpdateType._NODE_UPDATES_.ordinal();
207+
for(final ListIterator<DBUpdate> iter = dbUpdates.listIterator(); iter.hasNext();) {
208+
final DBUpdate up = iter.next();
209+
final int ord = up.type.ordinal();
210+
if(before ? ord < pos : ord > pos) {
211+
up.apply();
212+
iter.remove();
213+
}
214+
}
215+
}
216+
201217
/**
202218
* Prepares the {@link NodeUpdate} for execution incl. ordering,
203219
* and removes the update primitive references to save memory.
@@ -207,17 +223,13 @@ private List<NodeUpdate> preparePrimitives() {
207223
final List<NodeUpdate> upd = new ArrayList<>();
208224
for(int i = nodes.size() - 1; i >= 0; i--) {
209225
final int pre = nodes.get(i);
210-
final NodeUpdates n = nodeUpdates.get(pre);
211-
for(final NodeUpdate p : n.finish()) {
212-
upd.add(p);
213-
size += p.size();
226+
for(final NodeUpdate up : nodeUpdates.get(pre).finish()) {
227+
upd.add(up);
228+
size += up.size();
214229
}
215230
}
216-
for(int i = dbUpdates.size() - 1; i >= 0; i--) {
217-
size += dbUpdates.get(i).size();
218-
}
219-
nodeUpdates = null;
220231
nodes = null;
232+
for(final DBUpdate up : dbUpdates) size += up.size();
221233
upd.sort(new NodeUpdateComparator());
222234
return upd;
223235
}

basex-core/src/main/java/org/basex/query/up/NameUpdates.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@ void apply(final boolean before) throws QueryException {
5555
final int pos = UpdateType._NODE_UPDATES_.ordinal();
5656
for(final NameUpdate up : nameUpdates) {
5757
final int ord = up.type.ordinal();
58-
if(before ? ord < pos : ord > pos) up.apply();
58+
if(before ? ord < pos : ord > pos) {
59+
up.apply();
60+
}
5961
}
6062
}
6163

basex-core/src/main/java/org/basex/query/up/primitives/UpdateType.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ public enum UpdateType {
2626
/** Alter backup. */ BACKUPALTER,
2727
/** Create backup. */ BACKUPCREATE,
2828

29+
/** Add binary resource. */ DBSTORE,
30+
2931
// Operations on nodes of existing databases
3032

3133
/** Dummy type, indicating start of node updates. */ _NODE_UPDATES_,
@@ -45,7 +47,6 @@ public enum UpdateType {
4547
// Operations on resources of existing databases
4648

4749
/** Add document. */ DBADD,
48-
/** Add binary resource. */ DBSTORE,
4950
/** Rename resource. */ DBRENAME,
5051
/** Delete resource. */ DBDELETE,
5152
/** Optimize database. */ DBOPTIMIZE,

basex-core/src/test/java/org/basex/query/expr/MixedTest.java

+10
Original file line numberDiff line numberDiff line change
@@ -277,4 +277,14 @@ public void gh1983() {
277277
query("db:create('" + NAME + "', json-to-xml('[1]')/*/*, '" + NAME + "')");
278278
query("db:open('" + NAME + "')/* => namespace-uri()", "http://www.w3.org/2005/xpath-functions");
279279
}
280+
281+
/** db:store: out of bounds. */
282+
@Test public void gh2100() {
283+
query("db:create('x', <x>A</x>, 'x.xml')");
284+
query("db:open('x') ! (delete node x, db:store('x', 'x.bin', x))");
285+
query("db:retrieve('x', 'x.bin')", "A");
286+
287+
query("db:create('x', <x>A</x>, 'x.xml')");
288+
query("db:open('x') ! (delete node x, db:add('x', x, 'y.xml'))");
289+
}
280290
}

0 commit comments

Comments
 (0)