1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4//
5// File: caparser.h
6//
7
8
9//
10
11//
12// ============================================================================
13
14#ifndef __CAPARSER_H__
15#define __CAPARSER_H__
16
17#include "stgpooli.h"
18
19class CustomAttributeParser {
20public:
21 CustomAttributeParser( // Constructor for CustomAttributeParser.
22 const void *pvBlob, // Pointer to the CustomAttribute blob.
23 ULONG cbBlob) // Size of the CustomAttribute blob.
24 : m_pbCur(reinterpret_cast<const BYTE*>(pvBlob)),
25 m_pbBlob(reinterpret_cast<const BYTE*>(pvBlob)),
26 m_cbBlob(cbBlob)
27 {
28 LIMITED_METHOD_CONTRACT;
29 }
30
31private:
32 signed __int8 GetI1()
33 {
34 LIMITED_METHOD_CONTRACT;
35 signed __int8 tmp = *reinterpret_cast<const signed __int8*>(m_pbCur);
36 m_pbCur += sizeof(signed __int8);
37 return tmp;
38 }
39 unsigned __int8 GetU1()
40 {
41 LIMITED_METHOD_CONTRACT;
42 unsigned __int8 tmp = *reinterpret_cast<const unsigned __int8*>(m_pbCur);
43 m_pbCur += sizeof(unsigned __int8);
44 return tmp;
45 }
46
47 signed __int16 GetI2()
48 {
49 LIMITED_METHOD_CONTRACT;
50 signed __int16 tmp = GET_UNALIGNED_VAL16(m_pbCur);
51 m_pbCur += sizeof(signed __int16);
52 return tmp;
53 }
54 unsigned __int16 GetU2()
55 {
56 LIMITED_METHOD_CONTRACT;
57 unsigned __int16 tmp = GET_UNALIGNED_VAL16(m_pbCur);
58 m_pbCur += sizeof(unsigned __int16 );
59 return tmp;
60 }
61
62 signed __int32 GetI4()
63 {
64 LIMITED_METHOD_CONTRACT;
65 signed __int32 tmp = GET_UNALIGNED_VAL32(m_pbCur);
66 m_pbCur += sizeof(signed __int32 );
67 return tmp;
68 }
69 unsigned __int32 GetU4()
70 {
71 LIMITED_METHOD_CONTRACT;
72 unsigned __int32 tmp = GET_UNALIGNED_VAL32(m_pbCur);
73 m_pbCur += sizeof(unsigned __int32 );
74 return tmp;
75 }
76
77 signed __int64 GetI8()
78 {
79 LIMITED_METHOD_CONTRACT;
80 signed __int64 tmp = GET_UNALIGNED_VAL64(m_pbCur);
81 m_pbCur += sizeof(signed __int64 );
82 return tmp;
83 }
84 unsigned __int64 GetU8()
85 {
86 LIMITED_METHOD_CONTRACT;
87 unsigned __int64 tmp = GET_UNALIGNED_VAL64(m_pbCur);
88 m_pbCur += sizeof(unsigned __int64 );
89 return tmp;
90 }
91
92public:
93 float GetR4()
94 {
95 LIMITED_METHOD_CONTRACT;
96 __int32 tmp = GET_UNALIGNED_VAL32(m_pbCur);
97 _ASSERTE(sizeof(__int32) == sizeof(float));
98 m_pbCur += sizeof(float);
99 return (float &)tmp;
100 }
101
102 double GetR8()
103 {
104 LIMITED_METHOD_CONTRACT;
105 __int64 tmp = GET_UNALIGNED_VAL64(m_pbCur);
106 _ASSERTE(sizeof(__int64) == sizeof(double));
107 m_pbCur += sizeof(double);
108 return (double &)tmp;
109 }
110
111private:
112 unsigned __int16 GetProlog()
113 {
114 WRAPPER_NO_CONTRACT;
115 unsigned __int16 val;
116 VERIFY(SUCCEEDED(GetProlog(&val)));
117 return val;
118 }
119
120 LPCUTF8 GetString(ULONG *pcbString)
121 {
122 WRAPPER_NO_CONTRACT;
123 LPCUTF8 val;
124 VERIFY(SUCCEEDED(GetString(&val, pcbString)));
125 return val;
126 }
127
128public:
129 HRESULT GetI1(signed __int8 *pVal)
130 {
131 WRAPPER_NO_CONTRACT;
132
133 if (BytesLeft() < (int) sizeof(signed __int8))
134 return META_E_CA_INVALID_BLOB;
135 *pVal = GetI1();
136 return S_OK;
137 }
138
139 HRESULT GetTag(CorSerializationType *pVal)
140 {
141 WRAPPER_NO_CONTRACT;
142 HRESULT hr;
143 signed __int8 tmp;
144 IfFailRet(GetI1(&tmp));
145 *pVal = (CorSerializationType)((unsigned __int8)tmp);
146 return hr;
147 }
148
149 HRESULT GetU1(unsigned __int8 *pVal)
150 {
151 WRAPPER_NO_CONTRACT;
152
153 if (BytesLeft() < (int) sizeof(unsigned __int8))
154 return META_E_CA_INVALID_BLOB;
155 *pVal = GetU1();
156 return S_OK;
157 }
158
159 HRESULT GetI2(signed __int16 *pVal)
160 {
161 WRAPPER_NO_CONTRACT;
162
163 if (BytesLeft() < (int) sizeof(signed __int16))
164 return META_E_CA_INVALID_BLOB;
165 *pVal = GetI2();
166 return S_OK;
167 }
168 HRESULT GetU2(unsigned __int16 *pVal)
169 {
170 WRAPPER_NO_CONTRACT;
171
172 if (BytesLeft() < (int) sizeof(unsigned __int16))
173 return META_E_CA_INVALID_BLOB;
174 *pVal = GetU2();
175 return S_OK;
176 }
177
178 HRESULT GetI4(signed __int32 *pVal)
179 {
180 WRAPPER_NO_CONTRACT;
181
182 if (BytesLeft() < (int) sizeof(signed __int32))
183 return META_E_CA_INVALID_BLOB;
184 *pVal = GetI4();
185 return S_OK;
186 }
187 HRESULT GetU4(unsigned __int32 *pVal)
188 {
189 WRAPPER_NO_CONTRACT;
190
191 if (BytesLeft() < (int) sizeof(unsigned __int32))
192 return META_E_CA_INVALID_BLOB;
193 *pVal = GetU4();
194 return S_OK;
195 }
196
197 HRESULT GetI8(signed __int64 *pVal)
198 {
199 WRAPPER_NO_CONTRACT;
200
201 if (BytesLeft() < (int) sizeof(signed __int64))
202 return META_E_CA_INVALID_BLOB;
203 *pVal = GetI8();
204 return S_OK;
205 }
206 HRESULT GetU8(unsigned __int64 *pVal)
207 {
208 WRAPPER_NO_CONTRACT;
209
210 if (BytesLeft() < (int) sizeof(unsigned __int64))
211 return META_E_CA_INVALID_BLOB;
212 *pVal = GetU8();
213 return S_OK;
214 }
215
216 HRESULT GetR4(float *pVal)
217 {
218 WRAPPER_NO_CONTRACT;
219
220 if (BytesLeft() < (int) sizeof(float))
221 return META_E_CA_INVALID_BLOB;
222 *pVal = GetR4();
223 return S_OK;
224 }
225 HRESULT GetR8(double *pVal)
226 {
227 WRAPPER_NO_CONTRACT;
228
229 if (BytesLeft() < (int) sizeof(double))
230 return META_E_CA_INVALID_BLOB;
231 *pVal = GetR8();
232 return S_OK;
233 }
234
235 HRESULT GetProlog(unsigned __int16 *pVal)
236 {
237 WRAPPER_NO_CONTRACT;
238
239 m_pbCur = m_pbBlob;
240
241 if (BytesLeft() < (int)(sizeof(BYTE) * 2))
242 return META_E_CA_INVALID_BLOB;
243
244 return GetU2(pVal);
245 }
246
247 // Added for compatibility with anyone that may emit
248 // blobs where the prolog is the only incorrect data.
249 HRESULT SkipProlog()
250 {
251 unsigned __int16 val;
252 return GetProlog(&val);
253 }
254
255 HRESULT ValidateProlog()
256 {
257 HRESULT hr;
258 unsigned __int16 val;
259 IfFailRet(GetProlog(&val));
260
261 if (val != 0x0001)
262 return META_E_CA_INVALID_BLOB;
263
264 return hr;
265 }
266
267 //
268 // IMPORTANT: the returned string is typically not null-terminated.
269 //
270 // This can return any of three distinct valid results:
271 // - NULL string, indicated by *pszString==NULL, *pcbString==0
272 // - empty string, indicated by *pszString!=NULL, *pcbString==0
273 // - non-empty string, indicated by *pdzString!=NULL, *pcbString!=0
274 // If you expect non-null or non-empty strings in your usage scenario,
275 // call the GetNonNullString and GetNonEmptyString helpers below.
276 //
277 HRESULT GetString(LPCUTF8 *pszString, ULONG *pcbString)
278 {
279 STATIC_CONTRACT_NOTHROW;
280 STATIC_CONTRACT_FORBID_FAULT;
281
282 HRESULT hr;
283
284 if (BytesLeft() == 0)
285 { // Need to check for NULL string sentinal (see below),
286 // so need to have at least one byte to read.
287 IfFailRet(META_E_CA_INVALID_BLOB);
288 }
289
290 if (*m_pbCur == 0xFF)
291 { // 0xFF indicates the NULL string, which is semantically
292 // different than the empty string.
293 *pszString = NULL;
294 *pcbString = 0;
295 m_pbCur++;
296 return S_OK;
297 }
298
299 // Get the length, pointer to data following the length.
300 return GetData((BYTE const **)pszString, pcbString);
301 }
302
303 //
304 // This can return any of two distinct valid results:
305 // - empty string, indicated by *pszString!=NULL, *pcbString==0
306 // - non-empty string, indicated by *pszString!=NULL, *pcbString!=0
307 // If you expect non-null or non-empty strings in your usage scenario,
308 // call the GetNonNullString and GetNonEmptyString helpers below.
309 //
310 HRESULT GetNonNullString(LPCUTF8 *pszString, ULONG *pcbString)
311 {
312 STATIC_CONTRACT_NOTHROW;
313 STATIC_CONTRACT_FORBID_FAULT;
314
315 HRESULT hr;
316
317 IfFailRet(GetString(pszString, pcbString));
318
319 if (*pszString == NULL)
320 {
321 return META_E_CA_INVALID_BLOB;
322 }
323
324 return S_OK;
325 }
326
327 //
328 // This function will only return success if the string is valid,
329 // non-NULL and non-empty; i.e., *pszString!=NULL, *pcbString!=0
330 //
331 HRESULT GetNonEmptyString(LPCUTF8 *pszString, ULONG *pcbString)
332 {
333 STATIC_CONTRACT_NOTHROW;
334 STATIC_CONTRACT_FORBID_FAULT;
335
336 HRESULT hr;
337
338 IfFailRet(GetNonNullString(pszString, pcbString));
339
340 if (*pcbString == 0)
341 {
342 return META_E_CA_INVALID_BLOB;
343 }
344
345 return S_OK;
346 }
347
348 // IMPORTANT: do not use with string fetching - use GetString instead.
349 HRESULT GetData(BYTE const **ppbData, ULONG *pcbData)
350 {
351 HRESULT hr;
352 IfFailRet(CPackedLen::SafeGetData(m_pbCur, m_pbBlob + m_cbBlob, pcbData, ppbData));
353 // Move past the data we just recovered
354 m_pbCur = *ppbData + *pcbData;
355
356 return S_OK;
357 }
358
359 // IMPORTANT: do not use with string fetching - use GetString instead.
360 HRESULT GetPackedValue(ULONG *pcbData)
361 {
362 return CPackedLen::SafeGetLength(m_pbCur, m_pbBlob + m_cbBlob, pcbData, &m_pbCur);
363 }
364
365 int BytesLeft()
366 {
367 LIMITED_METHOD_CONTRACT;
368 return (int)(m_cbBlob - (m_pbCur - m_pbBlob));
369 }
370
371private:
372 const BYTE *m_pbCur;
373 const BYTE *m_pbBlob;
374 ULONG m_cbBlob;
375};
376
377#endif // __CAPARSER_H__
378