Skip to content

Commit ea50aab

Browse files
committed
LUCENE-8592: Fix index sorting corruption due to numeric overflow
The merge sort of sorted segments can produce an invalid sort if the sort field is an Integer/Long that uses reverse order and contains values equal to Integer/Long#MIN_VALUE. These values are always sorted first during a merge (instead of last because of the reverse order) due to this bug. Indices affected by the bug can be detected by running the CheckIndex command on a distribution that contains the fix (7.6+).
1 parent b775ddc commit ea50aab

File tree

3 files changed

+16
-5
lines changed

3 files changed

+16
-5
lines changed

server/src/main/java/org/elasticsearch/action/search/AbstractSearchAsyncAction.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.elasticsearch.search.SearchShardTarget;
3535
import org.elasticsearch.search.internal.AliasFilter;
3636
import org.elasticsearch.search.internal.InternalSearchResponse;
37+
import org.elasticsearch.search.internal.SearchContext;
3738
import org.elasticsearch.search.internal.ShardSearchTransportRequest;
3839
import org.elasticsearch.transport.Transport;
3940

@@ -113,7 +114,11 @@ public final void start() {
113114
if (getNumShards() == 0) {
114115
//no search shards to search on, bail with empty response
115116
//(it happens with search across _all with no indices around and consistent with broadcast operations)
116-
listener.onResponse(new SearchResponse(InternalSearchResponse.empty(), null, 0, 0, 0, buildTookInMillis(),
117+
118+
boolean withTotalHits = request.source() != null ?
119+
// total hits is null in the response if the tracking of total hits is disabled
120+
request.source().trackTotalHitsUpTo() != SearchContext.TRACK_TOTAL_HITS_DISABLED : true;
121+
listener.onResponse(new SearchResponse(InternalSearchResponse.empty(withTotalHits), null, 0, 0, 0, buildTookInMillis(),
117122
ShardSearchFailure.EMPTY_ARRAY, clusters));
118123
return;
119124
}

server/src/main/java/org/elasticsearch/search/SearchHits.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,13 @@
4242
import static org.elasticsearch.common.xcontent.XContentParserUtils.ensureExpectedToken;
4343

4444
public final class SearchHits implements Streamable, ToXContentFragment, Iterable<SearchHit> {
45-
4645
public static SearchHits empty() {
46+
return empty(true);
47+
}
48+
49+
public static SearchHits empty(boolean withTotalHits) {
4750
// We shouldn't use static final instance, since that could directly be returned by native transport clients
48-
return new SearchHits(EMPTY, new TotalHits(0, Relation.EQUAL_TO), 0);
51+
return new SearchHits(EMPTY, withTotalHits ? new TotalHits(0, Relation.EQUAL_TO) : null, 0);
4952
}
5053

5154
public static final SearchHit[] EMPTY = new SearchHit[0];

server/src/main/java/org/elasticsearch/search/internal/InternalSearchResponse.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,12 @@
3535
* {@link SearchResponseSections} subclass that can be serialized over the wire.
3636
*/
3737
public class InternalSearchResponse extends SearchResponseSections implements Writeable, ToXContentFragment {
38-
3938
public static InternalSearchResponse empty() {
40-
return new InternalSearchResponse(SearchHits.empty(), null, null, null, false, null, 1);
39+
return empty(true);
40+
}
41+
42+
public static InternalSearchResponse empty(boolean withTotalHits) {
43+
return new InternalSearchResponse(SearchHits.empty(withTotalHits), null, null, null, false, null, 1);
4144
}
4245

4346
public InternalSearchResponse(SearchHits hits, InternalAggregations aggregations, Suggest suggest,

0 commit comments

Comments
 (0)