120 |
121 |
121 va_list ap; |
122 va_list ap; |
122 va_start(ap, count); |
123 va_start(ap, count); |
123 |
124 |
124 // get all args and overall length |
125 // get all args and overall length |
|
126 bool overflow = false; |
125 size_t slen = str.length; |
127 size_t slen = str.length; |
126 for (size_t i = 0; i < count; i++) { |
128 for (size_t i = 0; i < count; i++) { |
127 cxstring s = va_arg (ap, cxstring); |
129 cxstring s = va_arg (ap, cxstring); |
128 strings[i] = s; |
130 strings[i] = s; |
|
131 if (slen > SIZE_MAX - str.length) overflow = true; |
129 slen += s.length; |
132 slen += s.length; |
130 } |
133 } |
131 va_end(ap); |
134 va_end(ap); |
|
135 |
|
136 // abort in case of overflow |
|
137 if (overflow) { |
|
138 errno = EOVERFLOW; |
|
139 if (strings != strings_stack) { |
|
140 free(strings); |
|
141 } |
|
142 return (cxmutstr) { NULL, 0 }; |
|
143 } |
132 |
144 |
133 // reallocate or create new string |
145 // reallocate or create new string |
134 char *newstr; |
146 char *newstr; |
135 if (str.ptr == NULL) { |
147 if (str.ptr == NULL) { |
136 newstr = cxMalloc(alloc, slen + 1); |
148 newstr = cxMalloc(alloc, slen + 1); |
137 } else { |
149 } else { |
138 newstr = cxRealloc(alloc, str.ptr, slen + 1); |
150 newstr = cxRealloc(alloc, str.ptr, slen + 1); |
139 } |
151 } |
140 if (newstr == NULL) { |
152 if (newstr == NULL) { |
141 free(strings); |
153 if (strings != strings_stack) { |
|
154 free(strings); |
|
155 } |
142 return (cxmutstr) {NULL, 0}; |
156 return (cxmutstr) {NULL, 0}; |
143 } |
157 } |
144 str.ptr = newstr; |
158 str.ptr = newstr; |
145 |
159 |
146 // concatenate strings |
160 // concatenate strings |