@@ -124,6 +124,23 @@ void RTDEF(PointerAssociateRemapping)(Descriptor &pointer,
124
124
}
125
125
}
126
126
127
+ RT_API_ATTRS void *AllocateValidatedPointerPayload (std::size_t byteSize) {
128
+ // Add space for a footer to validate during deallocation.
129
+ constexpr std::size_t align{sizeof (std::uintptr_t )};
130
+ byteSize = ((byteSize / align) + 1 ) * align;
131
+ std::size_t total{byteSize + sizeof (std::uintptr_t )};
132
+ void *p{std::malloc (total)};
133
+ if (p) {
134
+ // Fill the footer word with the XOR of the ones' complement of
135
+ // the base address, which is a value that would be highly unlikely
136
+ // to appear accidentally at the right spot.
137
+ std::uintptr_t *footer{
138
+ reinterpret_cast <std::uintptr_t *>(static_cast <char *>(p) + byteSize)};
139
+ *footer = ~reinterpret_cast <std::uintptr_t >(p);
140
+ }
141
+ return p;
142
+ }
143
+
127
144
int RTDEF (PointerAllocate)(Descriptor &pointer, bool hasStat,
128
145
const Descriptor *errMsg, const char *sourceFile, int sourceLine) {
129
146
Terminator terminator{sourceFile, sourceLine};
@@ -137,22 +154,12 @@ int RTDEF(PointerAllocate)(Descriptor &pointer, bool hasStat,
137
154
elementBytes = pointer.raw ().elem_len = 0 ;
138
155
}
139
156
std::size_t byteSize{pointer.Elements () * elementBytes};
140
- // Add space for a footer to validate during DEALLOCATE.
141
- constexpr std::size_t align{sizeof (std::uintptr_t )};
142
- byteSize = ((byteSize + align - 1 ) / align) * align;
143
- std::size_t total{byteSize + sizeof (std::uintptr_t )};
144
- void *p{std::malloc (total)};
157
+ void *p{AllocateValidatedPointerPayload (byteSize)};
145
158
if (!p) {
146
159
return ReturnError (terminator, CFI_ERROR_MEM_ALLOCATION, errMsg, hasStat);
147
160
}
148
161
pointer.set_base_addr (p);
149
162
pointer.SetByteStrides ();
150
- // Fill the footer word with the XOR of the ones' complement of
151
- // the base address, which is a value that would be highly unlikely
152
- // to appear accidentally at the right spot.
153
- std::uintptr_t *footer{
154
- reinterpret_cast <std::uintptr_t *>(static_cast <char *>(p) + byteSize)};
155
- *footer = ~reinterpret_cast <std::uintptr_t >(p);
156
163
int stat{StatOk};
157
164
if (const DescriptorAddendum * addendum{pointer.Addendum ()}) {
158
165
if (const auto *derived{addendum->derivedType ()}) {
@@ -176,6 +183,27 @@ int RTDEF(PointerAllocateSource)(Descriptor &pointer, const Descriptor &source,
176
183
return stat;
177
184
}
178
185
186
+ static RT_API_ATTRS std::size_t GetByteSize (
187
+ const ISO::CFI_cdesc_t &descriptor) {
188
+ std::size_t rank{descriptor.rank };
189
+ const ISO::CFI_dim_t *dim{descriptor.dim };
190
+ std::size_t byteSize{descriptor.elem_len };
191
+ for (std::size_t j{0 }; j < rank; ++j) {
192
+ byteSize *= dim[j].extent ;
193
+ }
194
+ return byteSize;
195
+ }
196
+
197
+ bool RT_API_ATTRS ValidatePointerPayload (const ISO::CFI_cdesc_t &desc) {
198
+ std::size_t byteSize{GetByteSize (desc)};
199
+ constexpr std::size_t align{sizeof (std::uintptr_t )};
200
+ byteSize = ((byteSize / align) + 1 ) * align;
201
+ const void *p{desc.base_addr };
202
+ const std::uintptr_t *footer{reinterpret_cast <const std::uintptr_t *>(
203
+ static_cast <const char *>(p) + byteSize)};
204
+ return *footer == ~reinterpret_cast <std::uintptr_t >(p);
205
+ }
206
+
179
207
int RTDEF (PointerDeallocate)(Descriptor &pointer, bool hasStat,
180
208
const Descriptor *errMsg, const char *sourceFile, int sourceLine) {
181
209
Terminator terminator{sourceFile, sourceLine};
@@ -185,20 +213,9 @@ int RTDEF(PointerDeallocate)(Descriptor &pointer, bool hasStat,
185
213
if (!pointer.IsAllocated ()) {
186
214
return ReturnError (terminator, StatBaseNull, errMsg, hasStat);
187
215
}
188
- if (executionEnvironment.checkPointerDeallocation ) {
189
- // Validate the footer. This should fail if the pointer doesn't
190
- // span the entire object, or the object was not allocated as a
191
- // pointer.
192
- std::size_t byteSize{pointer.Elements () * pointer.ElementBytes ()};
193
- constexpr std::size_t align{sizeof (std::uintptr_t )};
194
- byteSize = ((byteSize + align - 1 ) / align) * align;
195
- void *p{pointer.raw ().base_addr };
196
- std::uintptr_t *footer{
197
- reinterpret_cast <std::uintptr_t *>(static_cast <char *>(p) + byteSize)};
198
- if (*footer != ~reinterpret_cast <std::uintptr_t >(p)) {
199
- return ReturnError (
200
- terminator, StatBadPointerDeallocation, errMsg, hasStat);
201
- }
216
+ if (executionEnvironment.checkPointerDeallocation &&
217
+ !ValidatePointerPayload (pointer.raw ())) {
218
+ return ReturnError (terminator, StatBadPointerDeallocation, errMsg, hasStat);
202
219
}
203
220
return ReturnError (terminator,
204
221
pointer.Destroy (/* finalize=*/ true , /* destroyPointers=*/ true , &terminator),
0 commit comments