winkernel_mm.c
Go to the documentation of this file.
1 /* Capstone Disassembly Engine */
2 /* By Satoshi Tanda <tanda.sat@gmail.com>, 2016 */
3 
4 #include "winkernel_mm.h"
5 #include <ntddk.h>
6 #include <Ntintsafe.h>
7 
8 // A pool tag for memory allocation
9 static const ULONG CS_WINKERNEL_POOL_TAG = 'kwsC';
10 
11 
12 // A structure to implement realloc()
13 typedef struct _CS_WINKERNEL_MEMBLOCK {
14  size_t size; // A number of bytes allocated
15  __declspec(align(MEMORY_ALLOCATION_ALIGNMENT))
16  char data[ANYSIZE_ARRAY]; // An address returned to a caller
18 
19 
20 // free()
22 {
23  if (ptr) {
24  ExFreePoolWithTag(CONTAINING_RECORD(ptr, CS_WINKERNEL_MEMBLOCK, data), CS_WINKERNEL_POOL_TAG);
25  }
26 }
27 
28 // malloc()
30 {
31  // Disallow zero length allocation because they waste pool header space and,
32  // in many cases, indicate a potential validation issue in the calling code.
33  NT_ASSERT(size);
34 
35  // FP; a use of NonPagedPool is required for Windows 7 support
36 #pragma prefast(suppress : 30030) // Allocating executable POOL_TYPE memory
37  size_t number_of_bytes = 0;
39  // A specially crafted size value can trigger the overflow.
40  // If the sum in a value that overflows or underflows the capacity of the type,
41  // the function returns NULL.
42  if (!NT_SUCCESS(RtlSizeTAdd(size, FIELD_OFFSET(CS_WINKERNEL_MEMBLOCK, data), &number_of_bytes))) {
43  return NULL;
44  }
45  block = (CS_WINKERNEL_MEMBLOCK *)ExAllocatePoolWithTag(
46  NonPagedPool, number_of_bytes, CS_WINKERNEL_POOL_TAG);
47  if (!block) {
48  return NULL;
49  }
50  block->size = size;
51 
52  return block->data;
53 }
54 
55 // calloc()
56 void * CAPSTONE_API cs_winkernel_calloc(size_t n, size_t size)
57 {
58  size_t total = n * size;
59 
60  void *new_ptr = cs_winkernel_malloc(total);
61  if (!new_ptr) {
62  return NULL;
63  }
64 
65  return RtlFillMemory(new_ptr, total, 0);
66 }
67 
68 // realloc()
70 {
71  void *new_ptr = NULL;
72  size_t current_size = 0;
73  size_t smaller_size = 0;
74 
75  if (!ptr) {
76  return cs_winkernel_malloc(size);
77  }
78 
79  new_ptr = cs_winkernel_malloc(size);
80  if (!new_ptr) {
81  return NULL;
82  }
83 
84  current_size = CONTAINING_RECORD(ptr, CS_WINKERNEL_MEMBLOCK, data)->size;
85  smaller_size = (current_size < size) ? current_size : size;
86  RtlCopyMemory(new_ptr, ptr, smaller_size);
88 
89  return new_ptr;
90 }
91 
92 // vsnprintf(). _vsnprintf() is available for drivers, but it differs from
93 // vsnprintf() in a return value and when a null-terminator is set.
94 // cs_winkernel_vsnprintf() takes care of those differences.
95 #pragma warning(push)
96 // Banned API Usage : _vsnprintf is a Banned API as listed in dontuse.h for
97 // security purposes.
98 #pragma warning(disable : 28719)
99 int CAPSTONE_API cs_winkernel_vsnprintf(char *buffer, size_t count, const char *format, va_list argptr)
100 {
101  int result = _vsnprintf(buffer, count, format, argptr);
102 
103  // _vsnprintf() returns -1 when a string is truncated, and returns "count"
104  // when an entire string is stored but without '\0' at the end of "buffer".
105  // In both cases, null-terminator needs to be added manually.
106  if (result == -1 || (size_t)result == count) {
107  buffer[count - 1] = '\0';
108  }
109 
110  if (result == -1) {
111  // In case when -1 is returned, the function has to get and return a number
112  // of characters that would have been written. This attempts so by retrying
113  // the same conversion with temp buffer that is most likely big enough to
114  // complete formatting and get a number of characters that would have been
115  // written.
116  char* tmp = cs_winkernel_malloc(0x1000);
117  if (!tmp) {
118  return result;
119  }
120 
121  result = _vsnprintf(tmp, 0x1000, format, argptr);
122  NT_ASSERT(result != -1);
124  }
125 
126  return result;
127 }
128 #pragma warning(pop)
ptr
char * ptr
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:45
_gevent_test_main.result
result
Definition: _gevent_test_main.py:96
http2_test_server.format
format
Definition: http2_test_server.py:118
total
size_t total
Definition: cord_analysis.cc:59
CS_WINKERNEL_POOL_TAG
static const ULONG CS_WINKERNEL_POOL_TAG
Definition: winkernel_mm.c:9
CS_WINKERNEL_MEMBLOCK
struct _CS_WINKERNEL_MEMBLOCK CS_WINKERNEL_MEMBLOCK
block
Block * block
Definition: protobuf/src/google/protobuf/descriptor.cc:1041
NT_SUCCESS
#define NT_SUCCESS(status)
Definition: winapi.h:52
cs_winkernel_vsnprintf
int CAPSTONE_API cs_winkernel_vsnprintf(char *buffer, size_t count, const char *format, va_list argptr)
Definition: winkernel_mm.c:99
_CS_WINKERNEL_MEMBLOCK
Definition: winkernel_mm.c:13
CAPSTONE_API
#define CAPSTONE_API
Definition: capstone.h:32
winkernel_mm.h
cs_winkernel_calloc
void *CAPSTONE_API cs_winkernel_calloc(size_t n, size_t size)
Definition: winkernel_mm.c:56
data
char data[kBufferLength]
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1006
buffer
char buffer[1024]
Definition: libuv/docs/code/idle-compute/main.c:8
n
int n
Definition: abseil-cpp/absl/container/btree_test.cc:1080
absl::time_internal::cctz::detail::align
CONSTEXPR_F fields align(second_tag, fields f) noexcept
Definition: abseil-cpp/absl/time/internal/cctz/include/cctz/civil_time_detail.h:325
count
int * count
Definition: bloaty/third_party/googletest/googlemock/test/gmock_stress_test.cc:96
cs_winkernel_malloc
void *CAPSTONE_API cs_winkernel_malloc(size_t size)
Definition: winkernel_mm.c:29
autogen_x86imm.tmp
tmp
Definition: autogen_x86imm.py:12
size
voidpf void uLong size
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
__declspec
__declspec(noreturn) void uv_fatal_error(const int errorno
cs_winkernel_free
void CAPSTONE_API cs_winkernel_free(void *ptr)
Definition: winkernel_mm.c:21
cs_winkernel_realloc
void *CAPSTONE_API cs_winkernel_realloc(void *ptr, size_t size)
Definition: winkernel_mm.c:69
_CS_WINKERNEL_MEMBLOCK::size
size_t size
Definition: winkernel_mm.c:14


grpc
Author(s):
autogenerated on Fri May 16 2025 03:00:53