VirtualBox

source: vbox/trunk/src/VBox/GuestHost/OpenGL/include/cr_unpack.h@ 78196

Last change on this file since 78196 was 78196, checked in by vboxsync, 6 years ago

Another build fix

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 7.6 KB
Line 
1/* Copyright (c) 2001, Stanford University
2 * All rights reserved.
3 *
4 * See the file LICENSE.txt for information on redistributing this software.
5 */
6
7#ifndef CR_UNPACK_H
8#define CR_UNPACK_H
9
10#include "cr_compiler.h"
11#include "cr_spu.h"
12#include "cr_protocol.h"
13#include "cr_mem.h"
14#include "cr_opcodes.h"
15
16#include <iprt/types.h>
17
18#ifdef __cplusplus
19extern "C" {
20#endif
21
22/**
23 * Unpacker state.
24 */
25typedef struct CrUnpackerState
26{
27 /** Opcodes which are going to be unpacked. */
28 const uint8_t *pbOpcodes;
29 /** NUmber of Opcodes to unpack. */
30 size_t cOpcodes;
31 /** Start of the data buffer to unpack. */
32 const uint8_t *pbUnpackData;
33 /** Number of bytes remaining the inpack buffer. */
34 size_t cbUnpackDataLeft;
35 /** Return pointer. */
36 CRNetworkPointer *pReturnPtr;
37 /** Writeback pointer. */
38 CRNetworkPointer *pWritebackPtr;
39 /** Pointer to the dispatch table to use. */
40 SPUDispatchTable *pDispatchTbl;
41 /** Status code from the unpacker (mostly returns VERR_BUFFER_OVERFLOW
42 * on error if one unpacker detected out of bounds buffer access). */
43 int rcUnpack;
44} CrUnpackerState;
45/** Pointer to an unpacker state. */
46typedef CrUnpackerState *PCrUnpackerState;
47/** Pointer to a const unpacker state. */
48typedef const CrUnpackerState *PCCrUnpackerState;
49
50DECLEXPORT(void) crUnpack(PCrUnpackerState pState);
51
52typedef enum
53{
54 CR_UNPACK_BUFFER_TYPE_GENERIC = 0,
55 CR_UNPACK_BUFFER_TYPE_CMDBLOCK_BEGIN,
56 CR_UNPACK_BUFFER_TYPE_CMDBLOCK_FLUSH,
57 CR_UNPACK_BUFFER_TYPE_CMDBLOCK_END
58} CR_UNPACK_BUFFER_TYPE;
59
60DECLEXPORT(CR_UNPACK_BUFFER_TYPE) crUnpackGetBufferType(const void *opcodes, unsigned int num_opcodes);
61
62#if defined(LINUX) || defined(WINDOWS)
63#define CR_UNALIGNED_ACCESS_OKAY
64#else
65#undef CR_UNALIGNED_ACCESS_OKAY
66#endif
67DECLEXPORT(double) crReadUnalignedDouble( const void *buffer );
68
69/**
70 * Paranoid helper for debug builds to make sure the buffer size is validated correctly.
71 */
72DECLINLINE(const void *) crUnpackAccessChk(PCCrUnpackerState pState, size_t cbAccessVerified,
73 size_t offAccess, size_t cbType)
74{
75 AssertMsg(offAccess + cbType <= cbAccessVerified,
76 ("CHECK_BUFFER_SIZE_STATIC() has a wrong size given (verified %zu bytes vs tried access %zu)!\n",
77 cbAccessVerified, offAccess + cbType));
78 RT_NOREF(cbAccessVerified, cbType);
79 return pState->pbUnpackData + offAccess;
80}
81
82/**
83 * Does a one time check whether the buffer has sufficient data to access at least a_cbAccess
84 * bytes. Sets an error for the state and returns.
85 *
86 * @note Should only be used in the prologue of a method.
87 * @remark The introduction of int_cbAccessVerified makes sure CHECK_BUFFER_SIZE_STATIC() is there in each method for at least
88 * some rudimentary sanity check (fails to compile otherwise).
89 */
90#define CHECK_BUFFER_SIZE_STATIC(a_pState, a_cbAccess) \
91 if (RT_UNLIKELY((a_pState)->cbUnpackDataLeft < (a_cbAccess))) \
92 { \
93 (a_pState)->rcUnpack = VERR_BUFFER_OVERFLOW; \
94 return; \
95 } \
96 size_t int_cbAccessVerified = (a_cbAccess)
97
98#define CHECK_BUFFER_SIZE_STATIC_LAST(a_pState, a_offAccessLast, a_Type) CHECK_BUFFER_SIZE_STATIC(a_pState, (a_offAccessLast) + sizeof( a_Type ))
99
100#define CHECK_BUFFER_SIZE_STATIC_UPDATE(a_pState, a_cbAccess) \
101 do \
102 { \
103 if (RT_UNLIKELY((a_pState)->cbUnpackDataLeft < (a_cbAccess))) \
104 { \
105 (a_pState)->rcUnpack = VERR_BUFFER_OVERFLOW; \
106 return; \
107 } \
108 int_cbAccessVerified = (a_cbAccess); \
109 } \
110 while (0)
111
112#define CHECK_BUFFER_SIZE_STATIC_UPDATE_LAST(a_pState, a_offAccessLast, a_Type) CHECK_BUFFER_SIZE_STATIC_UPDATE(a_pState, (a_offAccessLast) + sizeof( a_Type ))
113
114#define CHECK_ARRAY_SIZE_FROM_PTR_UPDATE_LAST(a_pState, a_pArrayStart, a_cElements, a_Type) \
115 CHECK_BUFFER_SIZE_STATIC_UPDATE(a_pState, ((const uint8_t *)a_pArrayStart - (a_pState)->pbUnpackData) + (a_cElements) * sizeof(a_Type))
116#define CHECK_ARRAY_SIZE_FROM_PTR_UPDATE_SZ_LAST(a_pState, a_pArrayStart, a_cElements, a_cbType) \
117 CHECK_BUFFER_SIZE_STATIC_UPDATE(a_pState, ((const uint8_t *)a_pArrayStart - (a_pState)->pbUnpackData) + (a_cElements) * (a_cbType))
118
119
120DECLINLINE(size_t) crUnpackAcccessChkStrUpdate(PCrUnpackerState pState, const char *psz, size_t *pcbVerified)
121{
122 size_t cchStr = 0;
123 size_t cbChkMax = pState->cbUnpackDataLeft - ((const uint8_t *)psz - pState->pbUnpackData);
124 void *pv = memchr((void *)psz, '\0', cbChkMax);
125 if (!pv)
126 {
127 pState->rcUnpack = VERR_BUFFER_OVERFLOW;
128 return ~(size_t)0;
129 }
130
131 cchStr = (uint8_t *)pv - pState->pbUnpackData + 1;
132 *pcbVerified = cchStr;
133
134 return cchStr;
135}
136
137#define CHECK_STRING_FROM_PTR_UPDATE_NO_RETURN(a_pState, a_pszStr) crUnpackAcccessChkStrUpdate((a_pState), (a_pszStr), &int_cbAccessVerified);
138
139#define CHECK_STRING_FROM_PTR_UPDATE_NO_SZ(a_pState, a_pszStr) \
140 do \
141 { \
142 size_t cchStr = crUnpackAcccessChkStrUpdate((a_pState), (a_pszStr), &int_cbAccessVerified); \
143 if (RT_UNLIKELY(cchStr == ~(size_t)0)) \
144 return; \
145 } \
146 while (0)
147
148/**
149 * Reads data at the given offset of the given type from the supplied data buffer.
150 */
151#define READ_DATA(a_pState, offset, type ) *(const type *)crUnpackAccessChk((a_pState), int_cbAccessVerified, (offset), sizeof( type ))
152
153#ifdef CR_UNALIGNED_ACCESS_OKAY
154#define READ_DOUBLE(a_pState, offset ) READ_DATA(a_pState, offset, GLdouble )
155#else
156#define READ_DOUBLE(a_pState, offset ) crReadUnalignedDouble(crUnpackAccessChk((a_pState), int_cbAccessVerified, (offset), sizeof( GLdouble ) ))
157#endif
158
159#define READ_NETWORK_POINTER(a_pState, offset ) (uint8_t *)crUnpackAccessChk((a_pState), int_cbAccessVerified, (offset), 0)
160#define DATA_POINTER(a_pState, offset, type ) ((type *) (crUnpackAccessChk((a_pState), int_cbAccessVerified, (offset), 0)) )
161
162#define DATA_POINTER_CHECK(a_pState, offset ) ((size_t)(offset) < (a_pState)->cbUnpackDataLeft)
163
164#define INCR_DATA_PTR(a_pState, delta ) \
165 do \
166 { \
167 if (RT_UNLIKELY((a_pState)->cbUnpackDataLeft < (size_t)(delta))) \
168 { \
169 (a_pState)->rcUnpack = VERR_BUFFER_OVERFLOW; \
170 return; \
171 } \
172 (a_pState)->pbUnpackData += (delta); \
173 (a_pState)->cbUnpackDataLeft -= (delta); \
174 } while(0)
175
176#define INCR_DATA_PTR_NO_ARGS(a_pState) INCR_DATA_PTR(a_pState, 4 )
177
178#define INCR_VAR_PTR(a_pState) INCR_DATA_PTR(a_pState, *((int *)(a_pState)->pbUnpackData) )
179
180#define SET_RETURN_PTR(a_pState, offset ) \
181 do \
182 { \
183 CRDBGPTR_CHECKZ((a_pState)->pReturnPtr); \
184 if (!DATA_POINTER_CHECK(a_pState, offset + sizeof(*(a_pState)->pReturnPtr))) \
185 { \
186 crError("%s: SET_RETURN_PTR(%u) offset out of bounds\n", __FUNCTION__, offset); \
187 return; \
188 } \
189 crMemcpy((a_pState)->pReturnPtr, crUnpackAccessChk((a_pState), int_cbAccessVerified, (offset), sizeof( *(a_pState)->pReturnPtr )), sizeof( *(a_pState)->pReturnPtr ) ); \
190 } while (0)
191
192#define SET_WRITEBACK_PTR(a_pState, offset ) \
193 do \
194 { \
195 CRDBGPTR_CHECKZ((a_pState)->pWritebackPtr); \
196 if (!DATA_POINTER_CHECK(a_pState, offset + sizeof(*(a_pState)->pWritebackPtr))) \
197 { \
198 crError("%s: SET_RETURN_PTR(%u) offset out of bounds\n", __FUNCTION__, offset); \
199 return; \
200 } \
201 crMemcpy((a_pState)->pWritebackPtr, crUnpackAccessChk((a_pState), int_cbAccessVerified, (offset), sizeof( *(a_pState)->pWritebackPtr )), sizeof( *(a_pState)->pWritebackPtr) ); \
202 } while (0);
203
204#ifdef __cplusplus
205}
206#endif
207
208#endif /* CR_UNPACK_H */
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette