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 | |
19 | class CustomAttributeParser { |
20 | public: |
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 | |
31 | private: |
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 | |
92 | public: |
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 | |
111 | private: |
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 | |
128 | public: |
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 | |
371 | private: |
372 | const BYTE *m_pbCur; |
373 | const BYTE *m_pbBlob; |
374 | ULONG m_cbBlob; |
375 | }; |
376 | |
377 | #endif // __CAPARSER_H__ |
378 | |