Bug Summary

File:lwan-coro.c
Location:line 219, column 20
Description:Cast a region whose size is not a multiple of the destination type size

Annotated Source Code

1/*
2 * lwan - simple web server
3 * Copyright (c) 2012 Leandro A. F. Pereira <leandro@hardinfo.org>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19
20#define _GNU_SOURCE
21#include <assert.h>
22#include <limits.h>
23#include <stdarg.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27
28#include "lwan-private.h"
29
30#include "lwan-coro.h"
31
32#ifdef USE_VALGRIND
33#include <valgrind/valgrind.h>
34#endif
35
36#ifdef __GLIBC__2
37#define CORO_STACK_MIN((3 * (16384)) / 2) ((3 * (PTHREAD_STACK_MIN16384)) / 2)
38#else
39#define CORO_STACK_MIN((3 * (16384)) / 2) (5 * (PTHREAD_STACK_MIN16384))
40#endif
41
42static_assert(DEFAULT_BUFFER_SIZE < (CORO_STACK_MIN + PTHREAD_STACK_MIN),extern int (*__Static_assert_function (void)) [!!sizeof (struct
{ int __error_if_negative: (4096 < (((3 * (16384)) / 2) +
16384)) ? 2 : -1; })]
43 "Request buffer fits inside coroutine stack")extern int (*__Static_assert_function (void)) [!!sizeof (struct
{ int __error_if_negative: (4096 < (((3 * (16384)) / 2) +
16384)) ? 2 : -1; })]
;
44
45typedef struct coro_defer_t_ coro_defer_t;
46
47typedef void (*defer_func)();
48
49struct coro_defer_t_ {
50 coro_defer_t *next;
51 defer_func func;
52 void *data1;
53 void *data2;
54};
55
56struct coro_t_ {
57 coro_switcher_t *switcher;
58 coro_context_t context;
59 int yield_value;
60
61#if !defined(NDEBUG) && defined(USE_VALGRIND)
62 unsigned int vg_stack_id;
63#endif
64
65 coro_defer_t *defer;
66 void *data;
67
68 bool_Bool ended;
69};
70
71static void coro_entry_point(coro_t *data, coro_function_t func);
72
73/*
74 * This swapcontext() implementation was obtained from glibc and modified
75 * slightly to not save/restore the floating point registers, unneeded
76 * registers, and signal mask. It is Copyright (C) 2001, 2002, 2003 Free
77 * Software Foundation, Inc and are distributed under GNU LGPL version 2.1
78 * (or later). I'm not sure if I can distribute them inside a GPL program;
79 * they're straightforward so I'm assuming there won't be any problem; if
80 * there is, I'll just roll my own.
81 * -- Leandro
82 */
83#if defined(__x86_64__1)
84void __attribute__((noinline))
85coro_swapcontext(coro_context_t *current, coro_context_t *other);
86 asm(
87 ".text\n\t"
88 ".p2align 4\n\t"
89#if defined(__APPLE__)
90 ".globl _coro_swapcontext\n\t"
91 "_coro_swapcontext:\n\t"
92#else
93 ".globl coro_swapcontext\n\t"
94 "coro_swapcontext:\n\t"
95#endif
96 "mov %rbx,0(%rdi)\n\t"
97 "mov %rbp,8(%rdi)\n\t"
98 "mov %r12,16(%rdi)\n\t"
99 "mov %r13,24(%rdi)\n\t"
100 "mov %r14,32(%rdi)\n\t"
101 "mov %r15,40(%rdi)\n\t"
102 "mov %rdi,48(%rdi)\n\t"
103 "mov %rsi,56(%rdi)\n\t"
104 "mov (%rsp),%rcx\n\t"
105 "mov %rcx,64(%rdi)\n\t"
106 "lea 0x8(%rsp),%rcx\n\t"
107 "mov %rcx,72(%rdi)\n\t"
108 "mov 72(%rsi),%rsp\n\t"
109 "mov 0(%rsi),%rbx\n\t"
110 "mov 8(%rsi),%rbp\n\t"
111 "mov 16(%rsi),%r12\n\t"
112 "mov 24(%rsi),%r13\n\t"
113 "mov 32(%rsi),%r14\n\t"
114 "mov 40(%rsi),%r15\n\t"
115 "mov 48(%rsi),%rdi\n\t"
116 "mov 64(%rsi),%rcx\n\t"
117 "mov 56(%rsi),%rsi\n\t"
118 "jmp *%rcx\n\t");
119#elif defined(__i386__)
120void __attribute__((noinline))
121coro_swapcontext(coro_context_t *current, coro_context_t *other);
122 asm(
123 ".text\n\t"
124 ".p2align 16\n\t"
125#if defined(__APPLE__)
126 ".globl _coro_swapcontext\n\t"
127 "_coro_swapcontext:\n\t"
128#else
129 ".globl coro_swapcontext\n\t"
130 "coro_swapcontext:\n\t"
131#endif
132 "movl 0x4(%esp),%eax\n\t"
133 "movl %ecx,0x1c(%eax)\n\t" /* ECX */
134 "movl %ebx,0x0(%eax)\n\t" /* EBX */
135 "movl %esi,0x4(%eax)\n\t" /* ESI */
136 "movl %edi,0x8(%eax)\n\t" /* EDI */
137 "movl %ebp,0xc(%eax)\n\t" /* EBP */
138 "movl (%esp),%ecx\n\t"
139 "movl %ecx,0x14(%eax)\n\t" /* EIP */
140 "leal 0x4(%esp),%ecx\n\t"
141 "movl %ecx,0x18(%eax)\n\t" /* ESP */
142 "movl 8(%esp),%eax\n\t"
143 "movl 0x14(%eax),%ecx\n\t" /* EIP (1) */
144 "movl 0x18(%eax),%esp\n\t" /* ESP */
145 "pushl %ecx\n\t" /* EIP (2) */
146 "movl 0x0(%eax),%ebx\n\t" /* EBX */
147 "movl 0x4(%eax),%esi\n\t" /* ESI */
148 "movl 0x8(%eax),%edi\n\t" /* EDI */
149 "movl 0xc(%eax),%ebp\n\t" /* EBP */
150 "movl 0x1c(%eax),%ecx\n\t" /* ECX */
151 "ret\n\t");
152#else
153#define coro_swapcontext(cur,oth) swapcontext(cur, oth)
154#endif
155
156static void
157coro_entry_point(coro_t *coro, coro_function_t func)
158{
159 int return_value = func(coro);
160 coro->ended = true1;
161 coro_yield(coro, return_value);
162}
163
164static void
165coro_run_deferred(coro_t *coro)
166{
167 while (coro->defer) {
168 coro_defer_t *tmp = coro->defer;
169
170 coro->defer = coro->defer->next;
171
172 tmp->func(tmp->data1, tmp->data2);
173 free(tmp);
174 }
175}
176
177void
178coro_reset(coro_t *coro, coro_function_t func, void *data)
179{
180 unsigned char *stack = (unsigned char *)(coro + 1);
181
182 coro->ended = false0;
183 coro->data = data;
184
185 coro_run_deferred(coro);
186
187#if defined(__x86_64__1)
188 coro->context[6 /* RDI */] = (uintptr_t) coro;
189 coro->context[7 /* RSI */] = (uintptr_t) func;
190 coro->context[8 /* RIP */] = (uintptr_t) coro_entry_point;
191 coro->context[9 /* RSP */] = (uintptr_t) stack + CORO_STACK_MIN((3 * (16384)) / 2);
192#elif defined(__i386__)
193 /* Align stack and make room for two arguments */
194 stack = (unsigned char *)((uintptr_t)(stack + CORO_STACK_MIN((3 * (16384)) / 2) -
195 sizeof(uintptr_t) * 2) & 0xfffffff0);
196
197 uintptr_t *argp = (uintptr_t *)stack;
198 *argp++ = 0;
199 *argp++ = (uintptr_t)coro;
200 *argp++ = (uintptr_t)func;
201
202 coro->context[5 /* EIP */] = (uintptr_t) coro_entry_point;
203 coro->context[6 /* ESP */] = (uintptr_t) stack;
204#else
205 getcontext(&coro->context);
206
207 coro->context.uc_stack.ss_sp = stack;
208 coro->context.uc_stack.ss_size = CORO_STACK_MIN((3 * (16384)) / 2);
209 coro->context.uc_stack.ss_flags = 0;
210 coro->context.uc_link = NULL((void*)0);
211
212 makecontext(&coro->context, (void (*)())coro_entry_point, 2, coro, func);
213#endif
214}
215
216ALWAYS_INLINEinline __attribute__((always_inline)) coro_t *
217coro_new(coro_switcher_t *switcher, coro_function_t function, void *data)
218{
219 coro_t *coro = malloc(sizeof(*coro) + CORO_STACK_MIN((3 * (16384)) / 2));
Cast a region whose size is not a multiple of the destination type size
220 if (!coro)
221 return NULL((void*)0);
222
223 coro->switcher = switcher;
224 coro->defer = NULL((void*)0);
225 coro_reset(coro, function, data);
226
227#if !defined(NDEBUG) && defined(USE_VALGRIND)
228 char *stack = (char *)(coro + 1);
229 coro->vg_stack_id = VALGRIND_STACK_REGISTER(stack, stack + CORO_STACK_MIN)(unsigned)__extension__ ({ volatile unsigned long int _zzq_args
[6]; volatile unsigned long int _zzq_result; _zzq_args[0] = (
unsigned long int)(VG_USERREQ__STACK_REGISTER); _zzq_args[1] =
(unsigned long int)(stack); _zzq_args[2] = (unsigned long int
)(stack + ((3 * (16384)) / 2)); _zzq_args[3] = (unsigned long
int)(0); _zzq_args[4] = (unsigned long int)(0); _zzq_args[5]
= (unsigned long int)(0); __asm__ volatile("rolq $3, %%rdi ; rolq $13, %%rdi\n\t"
"rolq $61, %%rdi ; rolq $51, %%rdi\n\t" "xchgq %%rbx,%%rbx" :
"=d" (_zzq_result) : "a" (&_zzq_args[0]), "0" (0) : "cc"
, "memory" ); _zzq_result; })
;
230#endif
231
232 return coro;
233}
234
235ALWAYS_INLINEinline __attribute__((always_inline)) void *
236coro_get_data(coro_t *coro)
237{
238 assert(coro)((coro) ? (void) (0) : __assert_fail ("coro", "/home/buildbot/lwan-worker/clang-analyze/build/common/lwan-coro.c"
, 238, __PRETTY_FUNCTION__))
;
239
240 return coro->data;
241}
242
243ALWAYS_INLINEinline __attribute__((always_inline)) int
244coro_resume(coro_t *coro)
245{
246 assert(coro)((coro) ? (void) (0) : __assert_fail ("coro", "/home/buildbot/lwan-worker/clang-analyze/build/common/lwan-coro.c"
, 246, __PRETTY_FUNCTION__))
;
247 assert(coro->ended == false)((coro->ended == 0) ? (void) (0) : __assert_fail ("coro->ended == false"
, "/home/buildbot/lwan-worker/clang-analyze/build/common/lwan-coro.c"
, 247, __PRETTY_FUNCTION__))
;
248
249#if defined(__x86_64__1) || defined(__i386__)
250 coro_swapcontext(&coro->switcher->caller, &coro->context);
251 if (!coro->ended)
252 memcpy(&coro->context, &coro->switcher->callee,
253 sizeof(coro->context));
254#else
255 coro_context_t prev_caller;
256
257 memcpy(&prev_caller, &coro->switcher->caller, sizeof(prev_caller));
258 coro_swapcontext(&coro->switcher->caller, &coro->context);
259 if (!coro->ended) {
260 memcpy(&coro->context, &coro->switcher->callee,
261 sizeof(coro->context));
262 memcpy(&coro->switcher->caller, &prev_caller,
263 sizeof(coro->switcher->caller));
264 }
265#endif
266
267 return coro->yield_value;
268}
269
270ALWAYS_INLINEinline __attribute__((always_inline)) int
271coro_resume_value(coro_t *coro, int value)
272{
273 assert(coro)((coro) ? (void) (0) : __assert_fail ("coro", "/home/buildbot/lwan-worker/clang-analyze/build/common/lwan-coro.c"
, 273, __PRETTY_FUNCTION__))
;
274 assert(coro->ended == false)((coro->ended == 0) ? (void) (0) : __assert_fail ("coro->ended == false"
, "/home/buildbot/lwan-worker/clang-analyze/build/common/lwan-coro.c"
, 274, __PRETTY_FUNCTION__))
;
275
276 coro->yield_value = value;
277 return coro_resume(coro);
278}
279
280ALWAYS_INLINEinline __attribute__((always_inline)) int
281coro_yield(coro_t *coro, int value)
282{
283 assert(coro)((coro) ? (void) (0) : __assert_fail ("coro", "/home/buildbot/lwan-worker/clang-analyze/build/common/lwan-coro.c"
, 283, __PRETTY_FUNCTION__))
;
284 coro->yield_value = value;
285 coro_swapcontext(&coro->switcher->callee, &coro->switcher->caller);
286 return coro->yield_value;
287}
288
289void
290coro_free(coro_t *coro)
291{
292 assert(coro)((coro) ? (void) (0) : __assert_fail ("coro", "/home/buildbot/lwan-worker/clang-analyze/build/common/lwan-coro.c"
, 292, __PRETTY_FUNCTION__))
;
293#if !defined(NDEBUG) && defined(USE_VALGRIND)
294 VALGRIND_STACK_DEREGISTER(coro->vg_stack_id)do { (void) __extension__ ({ volatile unsigned long int _zzq_args
[6]; volatile unsigned long int _zzq_result; _zzq_args[0] = (
unsigned long int)((VG_USERREQ__STACK_DEREGISTER)); _zzq_args
[1] = (unsigned long int)((coro->vg_stack_id)); _zzq_args[
2] = (unsigned long int)((0)); _zzq_args[3] = (unsigned long int
)((0)); _zzq_args[4] = (unsigned long int)((0)); _zzq_args[5]
= (unsigned long int)((0)); __asm__ volatile("rolq $3, %%rdi ; rolq $13, %%rdi\n\t"
"rolq $61, %%rdi ; rolq $51, %%rdi\n\t" "xchgq %%rbx,%%rbx" :
"=d" (_zzq_result) : "a" (&_zzq_args[0]), "0" (0) : "cc"
, "memory" ); _zzq_result; }); } while (0)
;
295#endif
296 coro_run_deferred(coro);
297 free(coro);
298}
299
300static void
301coro_defer_any(coro_t *coro, defer_func func, void *data1, void *data2)
302{
303 coro_defer_t *defer = malloc(sizeof(*defer));
304 if (UNLIKELY(!defer)__builtin_expect(((!defer)), (0)))
305 return;
306
307 assert(func)((func) ? (void) (0) : __assert_fail ("func", "/home/buildbot/lwan-worker/clang-analyze/build/common/lwan-coro.c"
, 307, __PRETTY_FUNCTION__))
;
308
309 /* Some uses require deferred statements are arranged in a stack. */
310 defer->next = coro->defer;
311 defer->func = func;
312 defer->data1 = data1;
313 defer->data2 = data2;
314 coro->defer = defer;
315}
316
317ALWAYS_INLINEinline __attribute__((always_inline)) void
318coro_defer(coro_t *coro, void (*func)(void *data), void *data)
319{
320 coro_defer_any(coro, func, data, NULL((void*)0));
321}
322
323ALWAYS_INLINEinline __attribute__((always_inline)) void
324coro_defer2(coro_t *coro, void (*func)(void *data1, void *data2),
325 void *data1, void *data2)
326{
327 coro_defer_any(coro, func, data1, data2);
328}
329
330void *
331coro_malloc_full(coro_t *coro, size_t size, void (*destroy_func)())
332{
333 coro_defer_t *defer = malloc(sizeof(*defer) + size);
334 if (UNLIKELY(!defer)__builtin_expect(((!defer)), (0)))
335 return NULL((void*)0);
336
337 defer->next = coro->defer;
338 defer->func = destroy_func;
339 defer->data1 = defer + 1;
340 defer->data2 = NULL((void*)0);
341
342 coro->defer = defer;
343
344 return defer + 1;
345}
346
347static void nothing()
348{
349}
350
351inline void *
352coro_malloc(coro_t *coro, size_t size)
353{
354 return coro_malloc_full(coro, size, nothing);
355}
356
357char *
358coro_strndup(coro_t *coro, const char *str, size_t max_len)
359{
360 const size_t len = max_len + 1;
361 char *dup = coro_malloc(coro, len);
362 if (LIKELY(dup)__builtin_expect((!!(dup)), (1))) {
363 memcpy(dup, str, len);
364 dup[len - 1] = '\0';
365 }
366 return dup;
367}
368
369char *
370coro_strdup(coro_t *coro, const char *str)
371{
372 return coro_strndup(coro, str, strlen(str));
373}
374
375char *
376coro_printf(coro_t *coro, const char *fmt, ...)
377{
378 va_list values;
379 int len;
380 char *tmp_str;
381
382 va_start(values, fmt)__builtin_va_start(values, fmt);
383 len = vasprintf(&tmp_str, fmt, values);
384 va_end(values)__builtin_va_end(values);
385
386 if (UNLIKELY(len < 0)__builtin_expect(((len < 0)), (0)))
387 return NULL((void*)0);
388
389 coro_defer(coro, CORO_DEFER(free)((void (*)(void *))(free)), tmp_str);
390 return tmp_str;
391}