Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix two instances of memcpy with overlapping source and destination. #324

Merged
merged 4 commits into from Jul 11, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 7 additions & 7 deletions numpy/core/src/multiarray/lowlevel_strided_loops.c.src
Expand Up @@ -151,7 +151,7 @@ static void
#else

/* unaligned copy and swap */
memcpy(dst, src, @elsize@);
memmove(dst, src, @elsize@);
# if @is_swap@ == 1
@swap@@elsize@(dst);
# elif @is_swap@ == 2
Expand Down Expand Up @@ -239,7 +239,7 @@ _strided_to_strided(char *dst, npy_intp dst_stride,
NpyAuxData *NPY_UNUSED(data))
{
while (N > 0) {
memcpy(dst, src, src_itemsize);
memmove(dst, src, src_itemsize);
dst += dst_stride;
src += src_stride;
--N;
Expand All @@ -255,7 +255,7 @@ _swap_strided_to_strided(char *dst, npy_intp dst_stride,
char *a, *b, c;

while (N > 0) {
memcpy(dst, src, src_itemsize);
memmove(dst, src, src_itemsize);
/* general in-place swap */
a = dst;
b = dst + src_itemsize - 1;
Expand All @@ -281,7 +281,7 @@ _swap_pair_strided_to_strided(char *dst, npy_intp dst_stride,
npy_intp itemsize_half = src_itemsize / 2;

while (N > 0) {
memcpy(dst, src, src_itemsize);
memmove(dst, src, src_itemsize);
/* general in-place swap */
a = dst;
b = dst + itemsize_half - 1;
Expand Down Expand Up @@ -312,7 +312,7 @@ _contig_to_contig(char *dst, npy_intp NPY_UNUSED(dst_stride),
npy_intp N, npy_intp src_itemsize,
NpyAuxData *NPY_UNUSED(data))
{
memcpy(dst, src, src_itemsize*N);
memmove(dst, src, src_itemsize*N);
}


Expand Down Expand Up @@ -802,7 +802,7 @@ static void
src_value = *((_TYPE1 *)src);
# endif
#else
memcpy(&src_value, src, sizeof(src_value));
memmove(&src_value, src, sizeof(src_value));
#endif

/* Do the cast */
Expand Down Expand Up @@ -838,7 +838,7 @@ static void
*((_TYPE2 *)dst) = dst_value;
# endif
#else
memcpy(dst, &dst_value, sizeof(dst_value));
memmove(dst, &dst_value, sizeof(dst_value));
#endif

#if @contig@
Expand Down
78 changes: 78 additions & 0 deletions numpy/core/tests/test_multiarray_assignment.py
@@ -0,0 +1,78 @@
import numpy as np
from numpy.testing import TestCase

ndims = 2
size = 10
shape = tuple([size] * ndims)


def _indices_for_nelems(nelems):
"""Returns slices of length nelems, from start onwards, in direction sign."""

if nelems == 0:
return [size // 2] # int index

res = []
for step in (1, 2):
for sign in (-1, 1):
start = size // 2 - nelems * step * sign // 2
stop = start + nelems * step * sign
res.append(slice(start, stop, step * sign))

return res


def _indices_for_axis():
"""Returns (src, dst) pairs of indices."""

res = []
for nelems in (0, 2, 3):
ind = _indices_for_nelems(nelems)

# no itertools.product available in Py2.4
res.extend([(a, b) for a in ind for b in ind]) # all assignments of size "nelems"

return res


def _indices(ndims):
"""Returns ((axis0_src, axis0_dst), (axis1_src, axis1_dst), ... ) index pairs."""

ind = _indices_for_axis()

# no itertools.product available in Py2.4

res = [[]]
for i in xrange(ndims):
newres = []
for elem in ind:
for others in res:
newres.append([elem] + others)
res = newres

return res


def _check_assignment(srcidx, dstidx):
"""Check assignment arr[dstidx] = arr[srcidx] works."""

arr = np.arange(np.product(shape)).reshape(shape)

cpy = arr.copy()

cpy[dstidx] = arr[srcidx]
arr[dstidx] = arr[srcidx]

assert np.all(arr == cpy), 'assigning arr[%s] = arr[%s]' % (dstidx, srcidx)


def test_overlapping_assignments():
"""Test automatically generated assignments which overlap in memory."""

inds = _indices(ndims)

for ind in inds:
srcidx = tuple([a[0] for a in ind])
dstidx = tuple([a[1] for a in ind])

yield _check_assignment, srcidx, dstidx