Skip to content

Commit ef15a37

Browse files
original-brownbearcbuescher
authored andcommitted
Fix DLS using runtime fields and synthetic source (elastic#112341)
Somewhat of a tortured test but applying the same fix from elastic#112260 to synthetic source which was running into the same bug as a stored field source.
1 parent bc01b1e commit ef15a37

File tree

3 files changed

+52
-27
lines changed

3 files changed

+52
-27
lines changed

docs/changelog/112341.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 112341
2+
summary: Fix DLS using runtime fields and synthetic source
3+
area: Authorization
4+
type: bug
5+
issues: []

server/src/main/java/org/elasticsearch/search/lookup/SyntheticSourceProvider.java

Lines changed: 10 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,53 +8,37 @@
88

99
package org.elasticsearch.search.lookup;
1010

11-
import org.apache.lucene.index.IndexReaderContext;
1211
import org.apache.lucene.index.LeafReaderContext;
12+
import org.elasticsearch.common.util.concurrent.ConcurrentCollections;
1313
import org.elasticsearch.index.fieldvisitor.LeafStoredFieldLoader;
1414
import org.elasticsearch.index.fieldvisitor.StoredFieldLoader;
1515
import org.elasticsearch.index.mapper.SourceLoader;
1616

1717
import java.io.IOException;
18+
import java.util.Map;
1819

1920
// NB This is written under the assumption that individual segments are accessed by a single
2021
// thread, even if separate segments may be searched concurrently. If we ever implement
2122
// within-segment concurrency this will have to work entirely differently.
2223
class SyntheticSourceProvider implements SourceProvider {
2324

2425
private final SourceLoader sourceLoader;
25-
private volatile SyntheticSourceLeafLoader[] leafLoaders;
26+
private final Map<Object, SyntheticSourceLeafLoader> leaves = ConcurrentCollections.newConcurrentMap();
2627

2728
SyntheticSourceProvider(SourceLoader sourceLoader) {
2829
this.sourceLoader = sourceLoader;
2930
}
3031

3132
@Override
3233
public Source getSource(LeafReaderContext ctx, int doc) throws IOException {
33-
maybeInit(ctx);
34-
if (leafLoaders[ctx.ord] == null) {
35-
// individual segments are currently only accessed on one thread so there's no need
36-
// for locking here.
37-
leafLoaders[ctx.ord] = new SyntheticSourceLeafLoader(ctx);
34+
final Object id = ctx.id();
35+
var provider = leaves.get(id);
36+
if (provider == null) {
37+
provider = new SyntheticSourceLeafLoader(ctx);
38+
var existing = leaves.put(id, provider);
39+
assert existing == null : "unexpected source provider [" + existing + "]";
3840
}
39-
return leafLoaders[ctx.ord].getSource(doc);
40-
}
41-
42-
private void maybeInit(LeafReaderContext ctx) {
43-
if (leafLoaders == null) {
44-
synchronized (this) {
45-
if (leafLoaders == null) {
46-
leafLoaders = new SyntheticSourceLeafLoader[findParentContext(ctx).leaves().size()];
47-
}
48-
}
49-
}
50-
}
51-
52-
private IndexReaderContext findParentContext(LeafReaderContext ctx) {
53-
if (ctx.parent != null) {
54-
return ctx.parent;
55-
}
56-
assert ctx.isTopLevel;
57-
return ctx;
41+
return provider.getSource(doc);
5842
}
5943

6044
private class SyntheticSourceLeafLoader {

x-pack/plugin/security/src/internalClusterTest/java/org/elasticsearch/integration/DocumentLevelSecurityRandomTests.java

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,43 @@ public void testWithRuntimeFields() throws Exception {
144144
.endObject()
145145
)
146146
);
147+
doTestWithRuntimeFieldsInTestIndex();
148+
}
149+
150+
public void testWithRuntimeFieldsAndSyntheticSource() throws Exception {
151+
assertAcked(
152+
indicesAdmin().prepareCreate("test")
153+
.setMapping(
154+
XContentFactory.jsonBuilder()
155+
.startObject()
156+
.startObject("_source")
157+
.field("mode", "synthetic")
158+
.endObject()
159+
.startObject("runtime")
160+
.startObject("field1")
161+
.field("type", "keyword")
162+
.endObject()
163+
.startObject("field2")
164+
.field("type", "keyword")
165+
.endObject()
166+
.endObject()
167+
.startObject("properties")
168+
.startObject("field1")
169+
.field("type", "text")
170+
.field("store", true)
171+
.endObject()
172+
.startObject("field2")
173+
.field("type", "text")
174+
.field("store", true)
175+
.endObject()
176+
.endObject()
177+
.endObject()
178+
)
179+
);
180+
doTestWithRuntimeFieldsInTestIndex();
181+
}
182+
183+
private void doTestWithRuntimeFieldsInTestIndex() {
147184
List<IndexRequestBuilder> requests = new ArrayList<>(47);
148185
for (int i = 1; i <= 42; i++) {
149186
requests.add(prepareIndex("test").setSource("field1", "value1", "field2", "foo" + i));
@@ -158,5 +195,4 @@ public void testWithRuntimeFields() throws Exception {
158195
42L
159196
);
160197
}
161-
162198
}

0 commit comments

Comments
 (0)