Limit VADD REDUCE dim to not exceed original dim

* Limit VADD REDUCE dim to not exceed original dim

Enforce VADD key [REDUCE dim]  to reject dim that is bigger than the HNSW original dim, as dimension reduction makes no sense for reduce_dim > original_dim.
This also avoids OOM and possible heap overflow on later allocations using reduce_dim.

This should be backported to Redis version 8.0, 8.2 and 8.4.
This commit is contained in:
ofiryanai 2025-11-24 11:48:49 +02:00 committed by YaacovHazan
parent bc904dab04
commit c8f1ec959a
2 changed files with 36 additions and 0 deletions

View file

@ -65,3 +65,33 @@ class DimensionValidation(TestCase):
assert False, "VSIM with wrong dimension should fail"
except redis.exceptions.ResponseError as e:
assert "Input dimension mismatch for projection" in str(e), f"Expected dimension mismatch error in VSIM, got: {e}"
class ReduceDimConstraintValidation(TestCase):
def getname(self):
return "[regression] VADD enforces reduce_dim <= dim"
def estimated_runtime(self):
return 0.1
def test(self):
import struct
dim = 16
reduce_dim = dim + 1 # Intentionally larger than dim
# Build a simple FP32 vector of the given dimension.
vec = [0.0] * dim
vec_bytes = struct.pack(f'{dim}f', *vec)
try:
self.redis.execute_command(
'VADD', self.test_key,
'REDUCE', reduce_dim,
'FP32', vec_bytes,
f'{self.test_key}:item:reducemismatch')
assert False, "VADD with reduce_dim > dim should fail"
except redis.exceptions.ResponseError as e:
# Same generic validation error path as other vector spec problems.
assert "invalid vector specification" in str(e), (
f"Expected invalid vector error, got: {e}")

View file

@ -445,6 +445,12 @@ float *parseVector(RedisModuleString **argv, int argc, int start_idx,
return NULL; // Unknown format.
}
// reduce_dim must be <= dim
if (reduce_dim && *reduce_dim && *reduce_dim > *dim) {
if (vec) RedisModule_Free(vec);
return NULL;
}
if (consumed_args) *consumed_args = consumed;
return vec;
}