2 Commits
Author SHA1 Message Date
shashvat singhamandGeorge Panchuk 0f8a939259 fix: reject negative score indices in formula variables (#1341)
* fix: reject negative score indices in formula variables

qdrant core represents the score variable index as a usize
(VariableId::Score(usize)), so "$score[-1]" is not a valid pattern.
parse_variable used int(), which accepts a sign, underscore separators
and surrounding whitespace, and evaluate_variable then bounds-checks
with `var < len(scores)` -- a check that assumes a non-negative index.

A negative index therefore passed the check and read a prefetch from the
end of the list, while an out-of-range positive index correctly fell
back to the default score:

    scores = [{1: 10.0}, {1: 20.0}, {1: 30.0}]
    "$score[3]"  -> 0.0   (default, correct)
    "$score[-1]" -> 30.0  (silently the last prefetch)
    "$score[-9]" -> IndexError

Validate the index against the same grammar as core instead.

This is the same class of bug as the json path array index fixed in
#1340, in the formula parser rather than the payload one.

* fix: move tests into local tests

---------

Co-authored-by: George Panchuk <george.panchuk@qdrant.tech>
2026-09-16 00:28:02 +07:00
shashvat singhamandGeorge Panchuk 1860632b68 fix: validate sparse vectors with raises instead of asserts (#1343)
* fix: validate sparse vectors with raises instead of asserts

validate_sparse_vector checks user input, but does so with `assert`.
python -O strips assert statements, so under -O the checks disappear
entirely and a malformed sparse vector is accepted into a local
collection:

    $ python -O
    >>> client.upsert("t", [PointStruct(id=1, vector={"s": SparseVector(
    ...     indices=[1, 1, 1], values=[1.0, 1.0, 1.0])})])
    # accepted

The damage surfaces later rather than at the point of the mistake. A
vector whose indices and values have different lengths is stored, and a
subsequent query raises from deep inside the search path:

    >>> client.query_points("t", query=SparseVector(indices=[3], values=[1.0]), using="s")
    IndexError: list index out of range

Raise ValueError instead. This also stops user input being reported as
an AssertionError, which is inconsistent with the rest of the client.

* refactor: replace assert error with value error

* fix: validate vectors before write

* fix: add validation for update vectors and batch update points

* fix: validate vector dimensions and batch arguments before write

---------

Co-authored-by: George Panchuk <george.panchuk@qdrant.tech>
2026-09-16 00:27:57 +07:00