This fixes the overflow size_t possible problem in the string functions (yes,
[awesomized/libmemcached] / lib / memcached_string.c
1 #include "common.h"
2
3 memcached_return memcached_string_check(memcached_string_st *string, size_t need)
4 {
5 if (need > (size_t)(string->current_size - (size_t)(string->end - string->string)))
6 {
7 size_t current_offset= string->end - string->string;
8 char *new_value;
9 size_t adjust;
10 size_t new_size;
11
12 /* This is the block multiplier. To keep it larger and surive division errors we must round it up */
13 adjust= (need - (size_t)(string->current_size - (size_t)(string->end - string->string))) / string->block_size;
14 adjust++;
15
16 new_size= sizeof(char) * (size_t)((adjust * string->block_size) + string->current_size);
17 /* Test for overflow */
18 if (new_size < need)
19 return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
20
21 new_value= (char *)realloc(string->string, new_size);
22
23 if (new_value == NULL)
24 return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
25
26 string->string= new_value;
27 string->end= string->string + current_offset;
28
29 string->current_size+= (string->block_size * adjust);
30
31 /* We zero the block structure we just realloced */
32 memset((string->string + current_offset), 0,
33 sizeof(char) * string->block_size);
34 }
35
36 return MEMCACHED_SUCCESS;
37 }
38
39 memcached_string_st *memcached_string_create(memcached_st *ptr, size_t initial_size)
40 {
41 memcached_return rc;
42 memcached_string_st *string;
43
44 /* Saving malloc calls :) */
45 string= (memcached_string_st *)malloc(sizeof(memcached_string_st));
46 if (!string)
47 return NULL;
48 string->end= string->string;
49 memset(string, 0, sizeof(memcached_string_st));
50 string->block_size= initial_size;
51
52 rc= memcached_string_check(string, initial_size);
53 if (rc != MEMCACHED_SUCCESS)
54 {
55 free(string);
56 return NULL;
57 }
58
59 WATCHPOINT_ASSERT(string->string == string->end);
60
61 return string;
62 }
63
64 memcached_return memcached_string_append_character(memcached_st *ptr,
65 memcached_string_st *string,
66 char character)
67 {
68 memcached_return rc;
69
70 rc= memcached_string_check(string, 1);
71
72 if (rc != MEMCACHED_SUCCESS)
73 return rc;
74
75 *string->end= ' ';
76 string->end++;
77
78 return MEMCACHED_SUCCESS;
79 }
80
81 memcached_return memcached_string_append(memcached_st *ptr, memcached_string_st *string,
82 char *value, size_t length)
83 {
84 memcached_return rc;
85
86 rc= memcached_string_check(string, length);
87
88 if (rc != MEMCACHED_SUCCESS)
89 return rc;
90
91 WATCHPOINT_ASSERT(length <= string->current_size);
92 WATCHPOINT_ASSERT(string->string);
93 WATCHPOINT_ASSERT(string->end >= string->string);
94
95 memcpy(string->end, value, length);
96 string->end+= length;
97
98 return MEMCACHED_SUCCESS;
99 }
100
101 size_t memcached_string_backspace(memcached_st *ptr, memcached_string_st *string, size_t remove)
102 {
103 if (string->end - string->string > remove)
104 {
105 size_t difference;
106
107 difference= string->end - string->string;
108 string->end= string->string;
109
110 return difference;
111 }
112 string->end-= remove;
113
114 return remove;
115 }
116
117 memcached_return memcached_string_reset(memcached_st *ptr, memcached_string_st *string)
118 {
119 string->end= string->string;
120
121 return MEMCACHED_SUCCESS;
122 }
123
124 void memcached_string_free(memcached_st *ptr, memcached_string_st *string)
125 {
126 free(string->string);
127 free(string);
128 }