-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpadding.c
123 lines (104 loc) · 2.85 KB
/
padding.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/****************************************************************
* Experiments with casting between types of different sizes
* without losing track of the original size.
*
* Copyright Alastair Reid 2020
* SPDX-Licence-Identifier: BSD-3-Clause
****************************************************************/
#include "stdlib.h"
#include "stdint.h"
#include "malloc.h"
struct S {
uint32_t s;
};
struct T {
uint64_t t;
};
// To cast back and forth between pointers to different types,
// we need to pad the objects to some size that is at least
// as big as either of the types.
#define SIZE (sizeof(struct S) <= sizeof(struct T) ? sizeof(struct T) : sizeof(struct S))
/*@
predicate isPaddedS(struct S* s;) =
s->s |-> _
&*& struct_S_padding(s)
&*& chars((void*)s + sizeof(struct S), SIZE - sizeof(struct S), _)
;
predicate isPaddedT(struct T* t;) =
t->t |-> _
&*& struct_T_padding(t)
&*& chars((void*)t + sizeof(struct T), SIZE - sizeof(struct T), _)
;
@*/
/****************************************************************
* Constructors for S and T
****************************************************************/
struct S* mkS()
//@ requires true;
//@ ensures isPaddedS(result) &*& malloc_block(result, SIZE);
{
void *c = malloc(SIZE);
if (c == 0) abort();
//@ chars_split(c, sizeof(struct S));
struct S* s = (struct S*)c;
//@ close_struct(s);
return s;
}
struct T* mkT()
//@ requires true;
//@ ensures isPaddedT(result) &*& malloc_block(result, SIZE);
{
void *c = malloc(SIZE);
if (c == 0) abort();
//@ chars_split(c, sizeof(struct T));
struct T* t = (struct T*)c;
//@ close_struct(t);
return t;
}
/****************************************************************
* Conversions between S and T
****************************************************************/
struct S* t_to_s(struct T* t)
//@ requires isPaddedT(t);
//@ ensures isPaddedS(result);
{
//@ open_struct(t);
//@ chars_join((void*)t);
void *c = t;
//@ chars_split(c, sizeof(struct S));
struct S* s = (struct S*)c;
//@ close_struct(s);
return s;
}
struct T* s_to_t(struct S* s)
//@ requires isPaddedS(s);
//@ ensures isPaddedT(result);
{
//@ open_struct(s);
//@ chars_join((void*)s);
void *c = s;
//@ chars_split(c, sizeof(struct T));
struct T* t = (struct T*)c;
//@ close_struct(t);
return t;
}
/****************************************************************
* Sequential tests
****************************************************************/
// Sequential test code
void test_padding()
//@ requires true;
//@ ensures true;
{
struct S *s = mkS();
struct T *t = mkT();
struct T *pt = s_to_t(s);
struct S *ps = t_to_s(t);
//@ leak isPaddedS(ps);
//@ leak isPaddedT(pt);
//@ leak malloc_block(s, _);
//@ leak malloc_block(t, _);
}
/****************************************************************
* End
****************************************************************/