#700·annoy

[错误] 向 'get_nns_by_item' 或 'get_nns_by_vector' 传递负数作为 'n' 会导致结果不正确并发生整数溢出

作者: saitejabandaru-in创建于 2026年7月20日更新于 2026年7月20日

在使用 Python API 查询 Annoy 索引时,如果一个负整数(如 “n = -1 ”) 被传递为 “ get nns by-tem” 或 “ get nns by vector” 的 “n” 参数,则函数返回完全不正确的结果或空列表 `[] ,而不是丢出 Python 例外。

  • 复制
2zz
从烦恼导入 AnnoyIndex

t = AnoyIndex(10, “角” )
i 在范围(10):
v = [如果 j == = j = o = 0 = j 范围 (10)]
t.add 项目(一,五)
t. 建设( 10)

# 预期 : [0], 但得到完全无关的项目或空列表
打印(t.get nns by  item(0, -1))
打印(t.get nns by  item(0,-2))

根原因 : 在annoymodule.cc'中,n'被解释为已签名的`int32 t': 翻译: int32 t项,n, search k=-1,包括 距离=0; 如果 (! PyArg ParseTupleAndKeywords(args, kwargs, "ii" -- -- ii", (char**) kwlist, & item, &n, &search k, & including stars) ) , 则使用“ kwlit” 或“ kwlit” 。

但是,在`annoylib.h'中,相应的论据是未署名的`size tn':
翻译:
空取 nns by  item(S项,大小 t n, int search k,向量 <S>*QQ结果,向量 <T>*Q>*距离) const

n = -1'被通过时,其签号为SIZE MAX'(例如1844744073709551615')。

这导致在 QQget all nns 中出现连锁问题:

  1. Search k' Overflow**:search k=n * broot.size();'溢出。 由于search-k'是int',它默默地包围到一个负数。
  2. ** 无限制搜索条件**:(nns.size () < (signe t) search k !q.empty ())'将负数search k' 转换回SIZE MAX',导致搜索试图探索整个无限制树。
  3. ** " 目标结果 " **:大小-t p=n < m?n:m;评价为m ' (因为SIZE MAX < m'是虚假的),导致所有被探索的项目被退回。 由于无界限的勘探界限,这往往产生完全随机的错误项目或`[]'。

建议的修补 在“annoymodule.cc”中添加一个参数约束检查,以确保在给 C++ 核心打电话之前“n + 0”: 翻译: 如果(n < 0) { PyErr SetString( PyExc ValueError, “n必须是非负整数” ); 还原 NULL ; {\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}你觉得呢?