Skip to content

Commit 8462034

Browse files
committed
fix out of bound reads due to uninitialized variables
1 parent d4e7ff2 commit 8462034

File tree

4 files changed

+23
-7
lines changed

4 files changed

+23
-7
lines changed

HISTORY.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
## Changelog
22

33
### v0.18.0
4-
* Use a faster editops implementation provided by RapidFuzz
4+
#### Fixed
55
* Fixed memory leak in error path of setratio
6+
* Fixed out of bound reads due to uninitialized variable in median
7+
* e.g. quickmedian(["test", "teste"], [0, 0]) caused out of bound reads
8+
9+
#### Changed
10+
* Use a faster editops implementation provided by RapidFuzz
611
* Reduce code duplication
712
* reuse implementations from rapidfuzz-cpp
813
* Transition to scikit-build

src/cython/_levenshtein.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
#include <Python.h>
2525
#include "_levenshtein.hpp"
2626

27+
#include <iostream>
28+
2729
#define LEV_UNUSED(x) ((void)x)
2830

2931
/* Me thinks the second argument of PyArg_UnpackTuple() should be const.
@@ -299,7 +301,7 @@ setmedian_py(PyObject *self, PyObject *args)
299301
static PyObject*
300302
median_common(PyObject *args, const char *name, MedianFuncs foo)
301303
{
302-
size_t n, len;
304+
size_t n;
303305
void *strings = NULL;
304306
size_t *sizes = NULL;
305307
PyObject *strlist = NULL;
@@ -342,6 +344,7 @@ median_common(PyObject *args, const char *name, MedianFuncs foo)
342344

343345
if (stringtype == 0) {
344346
try {
347+
size_t len = 0;
345348
lev_byte *medstr = foo.s(n, sizes, (const lev_byte**)strings, weights, &len);
346349
if (!medstr && len)
347350
// todo remove after refactoring
@@ -357,6 +360,7 @@ median_common(PyObject *args, const char *name, MedianFuncs foo)
357360
}
358361
else if (stringtype == 1) {
359362
try {
363+
size_t len = 0;
360364
Py_UNICODE *medstr = foo.u(n, sizes, (const Py_UNICODE**)strings, weights, &len);
361365
if (!medstr && len)
362366
result = PyErr_NoMemory();
@@ -381,7 +385,7 @@ median_common(PyObject *args, const char *name, MedianFuncs foo)
381385
static PyObject*
382386
median_improve_common(PyObject *args, const char *name, MedianImproveFuncs foo)
383387
{
384-
size_t n, len;
388+
size_t n;
385389
void *strings = NULL;
386390
size_t *sizes = NULL;
387391
PyObject *arg1 = NULL;
@@ -436,6 +440,7 @@ median_improve_common(PyObject *args, const char *name, MedianImproveFuncs foo)
436440
Py_DECREF(strseq);
437441
if (stringtype == 0) {
438442
try {
443+
size_t len = 0;
439444
lev_byte *s = (lev_byte*)PyBytes_AS_STRING(arg1);
440445
size_t l = (size_t)PyBytes_GET_SIZE(arg1);
441446
lev_byte *medstr = foo.s(l, s, n, sizes, (const lev_byte**)strings, weights, &len);
@@ -452,6 +457,7 @@ median_improve_common(PyObject *args, const char *name, MedianImproveFuncs foo)
452457
}
453458
else if (stringtype == 1) {
454459
try {
460+
size_t len = 0;
455461
Py_UNICODE *s = PyUnicode_AS_UNICODE(arg1);
456462
size_t l = (size_t)PyUnicode_GET_SIZE(arg1);
457463
Py_UNICODE *medstr = foo.u(l, s, n, sizes, (const Py_UNICODE**)strings, weights, &len);

tests/test_levenshtein_distance.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
#!/usr/bin/env python
2-
# -*- coding: utf-8 -*-
3-
41
import Levenshtein
5-
import unittest
62

73
def test_empty_string():
84
"""

tests/test_median.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import Levenshtein
2+
3+
def test_weight_zero():
4+
"""
5+
Strings with zero weights should be ignored
6+
"""
7+
assert Levenshtein.quickmedian(["tes", "teste"], [0, 0]) == ""
8+
assert Levenshtein.quickmedian(["tes", "teste"], [1,0]) == "tes"
9+
assert Levenshtein.quickmedian(["tes", "teste"], [0,1]) == "teste"

0 commit comments

Comments
 (0)