Skip to content

Commit b14648c

Browse files
committed
add another test
1 parent 2dbda16 commit b14648c

3 files changed

Lines changed: 2643 additions & 0 deletions

File tree

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
// panic: refcount
2+
#include <assert.h>
3+
#include <stddef.h>
4+
#include <stdlib.h>
5+
#include <string.h>
6+
7+
struct In {
8+
short a;
9+
int b;
10+
};
11+
12+
struct S {
13+
int x;
14+
struct In in;
15+
unsigned char bytes[4];
16+
int arr[3];
17+
long tail;
18+
};
19+
20+
// The value of type T whose bytes are all v.
21+
#define REP(T, v) ((T)(0x0101010101010101ULL * (unsigned char)(v)))
22+
23+
static void set_bytes(unsigned char *p, size_t n, unsigned char v) {
24+
for (size_t i = 0; i < n; i++)
25+
p[i] = v;
26+
}
27+
28+
static int all_bytes(const unsigned char *p, size_t n, unsigned char v) {
29+
for (size_t i = 0; i < n; i++)
30+
if (p[i] != v)
31+
return 0;
32+
return 1;
33+
}
34+
35+
// Checks that field F of type T, at byte OFF of *s, is written through, in
36+
// both directions,
37+
// by the bytes of the field and by the bytes of the whole struct:
38+
// - bytes of the field -> field, and field -> bytes of the field,
39+
// - bytes of the struct -> field, and field -> bytes of the struct.
40+
// Leaves the field with all bytes equal to v + 3.
41+
#define CHECK_FIELD(s, F, T, OFF, v) \
42+
do { \
43+
unsigned char *fb = (unsigned char *)&(s)->F; \
44+
unsigned char *sb = (unsigned char *)(s) + (OFF); \
45+
set_bytes(fb, sizeof(T), (v)); \
46+
assert((s)->F == REP(T, (v))); \
47+
assert(all_bytes(sb, sizeof(T), (v))); \
48+
(s)->F = REP(T, (v) + 1); \
49+
assert(all_bytes(fb, sizeof(T), (v) + 1)); \
50+
assert(all_bytes(sb, sizeof(T), (v) + 1)); \
51+
set_bytes(sb, sizeof(T), (v) + 2); \
52+
assert((s)->F == REP(T, (v) + 2)); \
53+
assert(all_bytes(fb, sizeof(T), (v) + 2)); \
54+
(s)->F = REP(T, (v) + 3); \
55+
assert(all_bytes(sb, sizeof(T), (v) + 3)); \
56+
assert(all_bytes(fb, sizeof(T), (v) + 3)); \
57+
} while (0)
58+
59+
// Checks that all fields hold the values CHECK_FIELD left in them, i.e., that
60+
// no write through bytes clobbered a sibling field.
61+
static void check_final(struct S *s) {
62+
assert(s->x == REP(int, 0x13));
63+
assert(s->in.a == REP(short, 0x23));
64+
assert(s->in.b == REP(int, 0x33));
65+
assert(s->bytes[0] == 0x43 && s->bytes[1] == 0x53);
66+
assert(s->bytes[2] == 0x63 && s->bytes[3] == 0x73);
67+
assert(s->arr[0] == REP(int, 0x83) && s->arr[1] == REP(int, 0x93));
68+
assert(s->arr[2] == REP(int, 0x0b));
69+
assert(s->tail == REP(long, 0x1b));
70+
}
71+
72+
#define IN_OFF offsetof(struct S, in)
73+
#define BYTES_OFF offsetof(struct S, bytes)
74+
#define ARR_OFF offsetof(struct S, arr)
75+
76+
static void check_struct(struct S *s) {
77+
// Scalar fields, fields of a nested struct, and array elements.
78+
CHECK_FIELD(s, x, int, offsetof(struct S, x), 0x10);
79+
CHECK_FIELD(s, in.a, short, IN_OFF + offsetof(struct In, a), 0x20);
80+
CHECK_FIELD(s, in.b, int, IN_OFF + offsetof(struct In, b), 0x30);
81+
CHECK_FIELD(s, bytes[0], unsigned char, BYTES_OFF + 0, 0x40);
82+
CHECK_FIELD(s, bytes[1], unsigned char, BYTES_OFF + 1, 0x50);
83+
CHECK_FIELD(s, bytes[2], unsigned char, BYTES_OFF + 2, 0x60);
84+
CHECK_FIELD(s, bytes[3], unsigned char, BYTES_OFF + 3, 0x70);
85+
CHECK_FIELD(s, arr[0], int, ARR_OFF + 0 * sizeof(int), 0x80);
86+
CHECK_FIELD(s, arr[1], int, ARR_OFF + 1 * sizeof(int), 0x90);
87+
CHECK_FIELD(s, arr[2], int, ARR_OFF + 2 * sizeof(int), 0x08);
88+
CHECK_FIELD(s, tail, long, offsetof(struct S, tail), 0x18);
89+
check_final(s);
90+
91+
// A nested struct as a whole, through its bytes.
92+
set_bytes((unsigned char *)&s->in, sizeof(struct In), 0x21);
93+
assert(s->in.a == REP(short, 0x21) && s->in.b == REP(int, 0x21));
94+
struct In in = {REP(short, 0x23), REP(int, 0x33)};
95+
s->in = in;
96+
assert(all_bytes((unsigned char *)&s->in.a, sizeof(short), 0x23));
97+
assert(all_bytes((unsigned char *)&s->in.b, sizeof(int), 0x33));
98+
99+
// Array fields as a whole, through their bytes and through a different
100+
// element type.
101+
set_bytes((unsigned char *)s->arr, sizeof(s->arr), 0x85);
102+
assert(s->arr[0] == REP(int, 0x85) && s->arr[2] == REP(int, 0x85));
103+
set_bytes((unsigned char *)&s->arr, sizeof(s->arr), 0x86);
104+
assert(s->arr[1] == REP(int, 0x86));
105+
s->arr[0] = REP(int, 0x83);
106+
s->arr[1] = REP(int, 0x93);
107+
s->arr[2] = REP(int, 0x0b);
108+
int *ib = (int *)s->bytes;
109+
*ib = REP(int, 0x45);
110+
assert(all_bytes(s->bytes, sizeof(s->bytes), 0x45));
111+
s->bytes[0] = 0x43;
112+
s->bytes[1] = 0x53;
113+
s->bytes[2] = 0x63;
114+
s->bytes[3] = 0x73;
115+
assert(*ib == *(int *)(unsigned char *)&s->bytes);
116+
117+
// Through void *, memcpy and memset.
118+
void *v = &s->in.b;
119+
*(int *)v = 11;
120+
assert(s->in.b == 11);
121+
int twelve = 12;
122+
memcpy(&s->x, &twelve, sizeof(int));
123+
assert(s->x == 12);
124+
memset(&s->in.b, 0x33, sizeof(int));
125+
memset(&s->x, 0x13, sizeof(int));
126+
check_final(s);
127+
}
128+
129+
int main(void) {
130+
// A struct on the stack.
131+
struct S local;
132+
memset(&local, 0, sizeof(local));
133+
check_struct(&local);
134+
135+
// A struct in an array.
136+
struct S arr[2];
137+
memset(arr, 0, sizeof(arr));
138+
check_struct(&arr[1]);
139+
assert(all_bytes((unsigned char *)&arr[0], sizeof(struct S), 0));
140+
141+
// A struct in malloc'ed memory, i.e., a view of a byte buffer.
142+
struct S *heap = calloc(1, sizeof(struct S));
143+
assert(heap != NULL);
144+
check_struct(heap);
145+
free(heap);
146+
147+
// A struct in a byte buffer that is written through the buffer.
148+
unsigned char *raw = malloc(sizeof(struct S));
149+
assert(raw != NULL);
150+
memset(raw, 0, sizeof(struct S));
151+
struct S *view = (struct S *)raw;
152+
check_struct(view);
153+
assert(raw[offsetof(struct S, tail)] == 0x1b);
154+
set_bytes(raw + offsetof(struct S, arr), sizeof(int), 0x77);
155+
assert(view->arr[0] == REP(int, 0x77));
156+
view->bytes[3] = 0x11;
157+
assert(raw[offsetof(struct S, bytes) + 3] == 0x11);
158+
free(raw);
159+
return 0;
160+
}

0 commit comments

Comments
 (0)