vfs: check userland buffers before reading them.
[haiku.git] / src / bin / debug / strace / TypeHandler.cpp
blob4275f8194143f004cc8163c2538b2e9d2bd10d37
1 /*
2 * Copyright 2005-2007, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Ingo Weinhold <bonefish@cs.tu-berlin.de>
7 * Hugo Santos <hugosantos@gmail.com>
8 */
10 #include "TypeHandler.h"
12 #include <string.h>
14 #include "Context.h"
15 #include "MemoryReader.h"
16 #include "Syscall.h"
18 template<typename value_t>
19 static inline value_t
20 get_value(const void *address)
22 if (sizeof(align_t) > sizeof(value_t))
23 return value_t(*(align_t*)address);
24 else
25 return *(value_t*)address;
28 // #pragma mark -
30 // create_pointer_type_handler
31 TypeHandler *
32 create_pointer_type_handler()
34 return new TypeHandlerImpl<const void*>();
37 // create_string_type_handler
38 TypeHandler *
39 create_string_type_handler()
41 return new TypeHandlerImpl<const char*>();
44 // #pragma mark -
46 // complete specializations
48 // void
49 template<>
50 string
51 TypeHandlerImpl<void>::GetParameterValue(Context &, Parameter *, const void *)
53 return "void";
56 template<>
57 string
58 TypeHandlerImpl<void>::GetReturnValue(Context &, uint64 value)
60 return "";
63 template<>
64 TypeHandler *
65 TypeHandlerFactory<void>::Create()
67 return new TypeHandlerImpl<void>();
70 // bool
71 template<>
72 string
73 TypeHandlerImpl<bool>::GetParameterValue(Context &, Parameter *,
74 const void *address)
76 return (*(const align_t*)address ? "true" : "false");
79 template<>
80 string
81 TypeHandlerImpl<bool>::GetReturnValue(Context &, uint64 value)
83 return (value ? "true" : "false");
86 template<>
87 TypeHandler *
88 TypeHandlerFactory<bool>::Create()
90 return new TypeHandlerImpl<bool>();
93 // read_string
94 static
95 string
96 read_string(Context &context, void *data)
98 if (data == NULL || !context.GetContents(Context::STRINGS))
99 return context.FormatPointer(data);
101 char buffer[256];
102 int32 bytesRead;
103 status_t error = context.Reader().Read(data, buffer, sizeof(buffer), bytesRead);
104 if (error == B_OK) {
105 // return string("\"") + string(buffer, bytesRead) + "\"";
106 //string result("\"");
107 //result += string(buffer, bytesRead);
108 //result += "\"";
109 //return result;
111 // TODO: Unless I'm missing something obvious, our STL string class is broken.
112 // The appended "\"" doesn't appear in either of the above cases.
114 int32 len = strnlen(buffer, sizeof(buffer));
115 char largeBuffer[259];
116 largeBuffer[0] = '"';
117 memcpy(largeBuffer + 1, buffer, len);
118 largeBuffer[len + 1] = '"';
119 largeBuffer[len + 2] = '\0';
120 return largeBuffer;
123 return context.FormatPointer(data) + " (" + strerror(error) + ")";
126 // const void*
127 template<>
128 string
129 TypeHandlerImpl<const void*>::GetParameterValue(Context &context, Parameter *,
130 const void *address)
132 return context.FormatPointer(*(void **)address);
135 template<>
136 string
137 TypeHandlerImpl<const void*>::GetReturnValue(Context &context, uint64 value)
139 return context.FormatPointer((void *)value);
142 // const char*
143 template<>
144 string
145 TypeHandlerImpl<const char*>::GetParameterValue(Context &context, Parameter *,
146 const void *address)
148 return read_string(context, *(void **)address);
151 template<>
152 string
153 TypeHandlerImpl<const char*>::GetReturnValue(Context &context, uint64 value)
155 return read_string(context, (void *)value);
158 EnumTypeHandler::EnumTypeHandler(const EnumMap &m) : fMap(m) {}
160 string
161 EnumTypeHandler::GetParameterValue(Context &context, Parameter *,
162 const void *address)
164 return RenderValue(context, get_value<unsigned int>(address));
167 string
168 EnumTypeHandler::GetReturnValue(Context &context, uint64 value)
170 return RenderValue(context, value);
173 string
174 EnumTypeHandler::RenderValue(Context &context, unsigned int value) const
176 if (context.GetContents(Context::ENUMERATIONS)) {
177 EnumMap::const_iterator i = fMap.find(value);
178 if (i != fMap.end() && i->second != NULL)
179 return i->second;
182 return context.FormatUnsigned(value);
185 TypeHandlerSelector::TypeHandlerSelector(const SelectMap &m, int sibling,
186 TypeHandler *def)
187 : fMap(m), fSibling(sibling), fDefault(def) {}
189 string
190 TypeHandlerSelector::GetParameterValue(Context &context, Parameter *param,
191 const void *address)
193 TypeHandler *target = fDefault;
195 int index = get_value<int>(context.GetValue(context.GetSibling(fSibling)));
197 SelectMap::const_iterator i = fMap.find(index);
198 if (i != fMap.end())
199 target = i->second;
201 return target->GetParameterValue(context, param, address);
204 string
205 TypeHandlerSelector::GetReturnValue(Context &context, uint64 value)
207 return fDefault->GetReturnValue(context, value);
210 template<typename Type>
211 static bool
212 obtain_pointer_data(Context &context, Type *data, void *address, uint32 what)
214 if (address == NULL || !context.GetContents(what))
215 return false;
217 int32 bytesRead;
219 status_t err = context.Reader().Read(address, data, sizeof(Type), bytesRead);
220 if (err != B_OK || bytesRead < (int32)sizeof(Type))
221 return false;
223 return true;
226 template<typename Type>
227 static string
228 format_signed_integer_pointer(Context &context, void *address)
230 Type data;
232 if (obtain_pointer_data(context, &data, address, Context::POINTER_VALUES))
233 return "[" + context.FormatSigned(data, sizeof(Type)) + "]";
235 return context.FormatPointer(address);
238 template<typename Type>
239 static string
240 format_unsigned_integer_pointer(Context &context, void *address)
242 Type data;
244 if (obtain_pointer_data(context, &data, address, Context::POINTER_VALUES))
245 return "[" + context.FormatUnsigned(data) + "]";
247 return context.FormatPointer(address);
250 template<typename Type>
251 class SignedIntegerTypeHandler : public TypeHandler {
252 public:
253 string GetParameterValue(Context &context, Parameter *,
254 const void *address)
256 return context.FormatSigned(get_value<Type>(address), sizeof(Type));
259 string GetReturnValue(Context &context, uint64 value)
261 return context.FormatSigned(value, sizeof(Type));
265 template<typename Type>
266 class UnsignedIntegerTypeHandler : public TypeHandler {
267 public:
268 string GetParameterValue(Context &context, Parameter *,
269 const void *address)
271 return context.FormatUnsigned(get_value<Type>(address));
274 string GetReturnValue(Context &context, uint64 value)
276 return context.FormatUnsigned(value);
280 template<typename Type>
281 class SignedIntegerPointerTypeHandler : public TypeHandler {
282 string GetParameterValue(Context &context, Parameter *,
283 const void *address)
285 return format_signed_integer_pointer<Type>(context, *(void **)address);
288 string GetReturnValue(Context &context, uint64 value)
290 return format_signed_integer_pointer<Type>(context, (void *)value);
294 template<typename Type>
295 class UnsignedIntegerPointerTypeHandler : public TypeHandler {
296 string GetParameterValue(Context &context, Parameter *,
297 const void *address)
299 return format_unsigned_integer_pointer<Type>(context, *(void **)address);
302 string GetReturnValue(Context &context, uint64 value)
304 return format_unsigned_integer_pointer<Type>(context, (void *)value);
308 #define SIGNED_INTEGER_TYPE(type) \
309 template<> \
310 TypeHandler * \
311 TypeHandlerFactory<type>::Create() \
313 return new SignedIntegerTypeHandler<type>(); \
316 #define UNSIGNED_INTEGER_TYPE(type) \
317 template<> \
318 TypeHandler * \
319 TypeHandlerFactory<type>::Create() \
321 return new UnsignedIntegerTypeHandler<type>(); \
324 #define SIGNED_INTEGER_POINTER_TYPE(name, type) \
325 TypeHandler *create_##name##_type_handler() \
327 return new SignedIntegerPointerTypeHandler<type>(); \
330 #define UNSIGNED_INTEGER_POINTER_TYPE(name, type) \
331 TypeHandler *create_##name##_type_handler() \
333 return new UnsignedIntegerPointerTypeHandler<type>(); \
337 SIGNED_INTEGER_TYPE(char);
338 SIGNED_INTEGER_TYPE(short);
339 SIGNED_INTEGER_TYPE(int);
340 SIGNED_INTEGER_TYPE(long);
341 SIGNED_INTEGER_TYPE(long long);
343 UNSIGNED_INTEGER_TYPE(unsigned char);
344 UNSIGNED_INTEGER_TYPE(unsigned short);
345 UNSIGNED_INTEGER_TYPE(unsigned int);
346 UNSIGNED_INTEGER_TYPE(unsigned long);
347 UNSIGNED_INTEGER_TYPE(unsigned long long);
349 SIGNED_INTEGER_POINTER_TYPE(int_ptr, int);
350 SIGNED_INTEGER_POINTER_TYPE(long_ptr, long);
351 SIGNED_INTEGER_POINTER_TYPE(longlong_ptr, long long);
353 UNSIGNED_INTEGER_POINTER_TYPE(uint_ptr, unsigned int);
354 UNSIGNED_INTEGER_POINTER_TYPE(ulong_ptr, unsigned long);
355 UNSIGNED_INTEGER_POINTER_TYPE(ulonglong_ptr, unsigned long long);