1// SPDX-License-Identifier: GPL-2.0
2#include <malloc.h>
3#include <string.h>
4#include <stdlib.h>
5#include <stdbool.h>
6
7#include "utils.h"
8
9#define MAX_LEN 8192
10#define MAX_OFFSET 16
11#define MIN_REDZONE 128
12#define BUFLEN (MAX_LEN+MAX_OFFSET+2*MIN_REDZONE)
13#define POISON 0xa5
14
15unsigned long COPY_LOOP(void *to, const void *from, unsigned long size);
16
17static void do_one(char *src, char *dst, unsigned long src_off,
18		   unsigned long dst_off, unsigned long len, void *redzone,
19		   void *fill)
20{
21	char *srcp, *dstp;
22	unsigned long ret;
23	unsigned long i;
24
25	srcp = src + MIN_REDZONE + src_off;
26	dstp = dst + MIN_REDZONE + dst_off;
27
28	memset(src, POISON, BUFLEN);
29	memset(dst, POISON, BUFLEN);
30	memcpy(srcp, fill, len);
31
32	ret = COPY_LOOP(dstp, srcp, len);
33	if (ret && ret != (unsigned long)dstp) {
34		printf("(%p,%p,%ld) returned %ld\n", dstp, srcp, len, ret);
35		abort();
36	}
37
38	if (memcmp(dstp, srcp, len)) {
39		printf("(%p,%p,%ld) miscompare\n", dstp, srcp, len);
40		printf("src: ");
41		for (i = 0; i < len; i++)
42			printf("%02x ", srcp[i]);
43		printf("\ndst: ");
44		for (i = 0; i < len; i++)
45			printf("%02x ", dstp[i]);
46		printf("\n");
47		abort();
48	}
49
50	if (memcmp(dst, redzone, dstp - dst)) {
51		printf("(%p,%p,%ld) redzone before corrupted\n",
52		       dstp, srcp, len);
53		abort();
54	}
55
56	if (memcmp(dstp+len, redzone, dst+BUFLEN-(dstp+len))) {
57		printf("(%p,%p,%ld) redzone after corrupted\n",
58		       dstp, srcp, len);
59		abort();
60	}
61}
62
63int test_copy_loop(void)
64{
65	char *src, *dst, *redzone, *fill;
66	unsigned long len, src_off, dst_off;
67	unsigned long i;
68
69	src = memalign(BUFLEN, BUFLEN);
70	dst = memalign(BUFLEN, BUFLEN);
71	redzone = malloc(BUFLEN);
72	fill = malloc(BUFLEN);
73
74	if (!src || !dst || !redzone || !fill) {
75		fprintf(stderr, "malloc failed\n");
76		exit(1);
77	}
78
79	memset(redzone, POISON, BUFLEN);
80
81	/* Fill with sequential bytes */
82	for (i = 0; i < BUFLEN; i++)
83		fill[i] = i & 0xff;
84
85	for (len = 1; len < MAX_LEN; len++) {
86		for (src_off = 0; src_off < MAX_OFFSET; src_off++) {
87			for (dst_off = 0; dst_off < MAX_OFFSET; dst_off++) {
88				do_one(src, dst, src_off, dst_off, len,
89				       redzone, fill);
90			}
91		}
92	}
93
94	return 0;
95}
96
97int main(void)
98{
99	return test_harness(test_copy_loop, str(COPY_LOOP));
100}
101