Bug Summary

File:techempower/database.c
Location:line 80, column 35
Description:Call to 'calloc' has an allocation size of 0 bytes

Annotated Source Code

1/*
2 * lwan - simple web server
3 * Copyright (c) 2014 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#include <mysql.h>
21#include <sqlite3.h>
22#include <stddef.h>
23#include <stdlib.h>
24
25#include "database.h"
26
27/* MySQL */
28
29struct db_mysql {
30 struct db base;
31 MYSQL *con;
32};
33
34struct db_stmt_mysql {
35 struct db_stmt base;
36 MYSQL_STMT *stmt;
37 MYSQL_BIND *param_bind;
38 MYSQL_BIND *result_bind;
39};
40
41static bool_Bool db_stmt_bind_mysql(const struct db_stmt *stmt,
42 struct db_row *rows, size_t n_rows)
43{
44 struct db_stmt_mysql *stmt_mysql = (struct db_stmt_mysql *)stmt;
45
46 stmt_mysql->param_bind = calloc(n_rows, sizeof(*stmt_mysql->param_bind));
47 if (!stmt_mysql->param_bind)
48 return false0;
49
50 for (size_t row = 0; row < n_rows; row++) {
51 if (rows[row].kind == '\0') break;
52
53 MYSQL_BIND *param = &stmt_mysql->param_bind[row];
54 if (rows[row].kind == 's') {
55 param->buffer_type = MYSQL_TYPE_STRING;
56 param->buffer = rows[row].u.s;
57 } else if (rows[row].kind == 'i') {
58 param->buffer_type = MYSQL_TYPE_LONG;
59 param->buffer = &rows[row].u.i;
60 }
61 param->is_null = false0;
62 param->length = 0;
63 }
64
65 return !mysql_stmt_bind_param(stmt_mysql->stmt, stmt_mysql->param_bind);
66}
67
68static bool_Bool db_stmt_step_mysql(const struct db_stmt *stmt, struct db_row *row)
69{
70 struct db_stmt_mysql *stmt_mysql = (struct db_stmt_mysql *)stmt;
71
72 if (!stmt_mysql->result_bind) {
1
Taking true branch
73 if (mysql_stmt_execute(stmt_mysql->stmt))
2
Taking false branch
74 return false0;
75
76 size_t n_rows = 0;
3
'n_rows' initialized to 0
77 for (struct db_row *r = row; r->kind != '\0'; r++)
4
Loop condition is false. Execution continues on line 80
78 n_rows++;
79
80 stmt_mysql->result_bind = calloc(n_rows, sizeof(*stmt_mysql->result_bind));
5
Call to 'calloc' has an allocation size of 0 bytes
81 if (!stmt_mysql->result_bind)
82 return false0;
83
84 stmt_mysql->param_bind = calloc(n_rows, sizeof(*stmt_mysql->param_bind));
85 if (!stmt_mysql->param_bind) {
86 free(stmt_mysql->param_bind);
87 return false0;
88 }
89
90 MYSQL_BIND *result = stmt_mysql->result_bind;
91 for (size_t r = 0; r < n_rows; r++) {
92 if (row[r].kind == 's') {
93 result[r].buffer_type = MYSQL_TYPE_STRING;
94 result[r].buffer = row[r].u.s;
95 } else if (row[r].kind == 'i') {
96 result[r].buffer_type = MYSQL_TYPE_LONG;
97 result[r].buffer = &row[r].u.i;
98 } else {
99 return false0;
100 }
101
102 result[r].is_null = false0;
103 result[r].buffer_length = row[r].buffer_length;
104 }
105
106 if (mysql_stmt_bind_result(stmt_mysql->stmt, result))
107 return false0;
108 }
109
110 return mysql_stmt_fetch(stmt_mysql->stmt) == 0;
111}
112
113static void db_stmt_finalize_mysql(struct db_stmt *stmt)
114{
115 struct db_stmt_mysql *stmt_mysql = (struct db_stmt_mysql *)stmt;
116
117 mysql_stmt_close(stmt_mysql->stmt);
118 free(stmt_mysql->result_bind);
119 free(stmt_mysql->param_bind);
120 free(stmt_mysql);
121}
122
123static struct db_stmt *db_prepare_mysql(const struct db *db, const char *sql,
124 const size_t sql_len)
125{
126 const struct db_mysql *db_mysql = (const struct db_mysql *)db;
127 struct db_stmt_mysql *stmt_mysql = malloc(sizeof(*stmt_mysql));
128
129 if (!stmt_mysql)
130 return NULL((void*)0);
131
132 stmt_mysql->stmt = mysql_stmt_init(db_mysql->con);
133 if (!stmt_mysql->stmt) {
134 free(stmt_mysql);
135 return NULL((void*)0);
136 }
137
138 if (mysql_stmt_prepare(stmt_mysql->stmt, sql, sql_len)) {
139 mysql_stmt_close(stmt_mysql->stmt);
140 free(stmt_mysql);
141 return NULL((void*)0);
142 }
143
144 stmt_mysql->base.bind = db_stmt_bind_mysql;
145 stmt_mysql->base.step = db_stmt_step_mysql;
146 stmt_mysql->base.finalize = db_stmt_finalize_mysql;
147 stmt_mysql->result_bind = NULL((void*)0);
148 stmt_mysql->param_bind = NULL((void*)0);
149
150 return (struct db_stmt*)stmt_mysql;
151}
152
153static void db_disconnect_mysql(struct db *db)
154{
155 struct db_mysql *db_mysql = (struct db_mysql *)db;
156
157 mysql_close(db_mysql->con);
158 free(db);
159}
160
161struct db *db_connect_mysql(const char *host, const char *user, const char *pass,
162 const char *database)
163{
164 struct db_mysql *db_mysql = malloc(sizeof(*db_mysql));
165
166 if (!db_mysql)
167 return NULL((void*)0);
168
169 db_mysql->con = mysql_init(NULL((void*)0));
170 if (!db_mysql->con) {
171 free(db_mysql);
172 return NULL((void*)0);
173 }
174
175 if (!mysql_real_connect(db_mysql->con, host, user, pass, database, 0, NULL((void*)0), 0))
176 goto error;
177
178 if (mysql_set_character_set(db_mysql->con, "utf8"))
179 goto error;
180
181 db_mysql->base.disconnect = db_disconnect_mysql;
182 db_mysql->base.prepare = db_prepare_mysql;
183
184 return (struct db *)db_mysql;
185
186error:
187 mysql_close(db_mysql->con);
188 free(db_mysql);
189 return NULL((void*)0);
190}
191
192/* SQLite */
193
194struct db_sqlite {
195 struct db base;
196 sqlite3 *sqlite;
197};
198
199struct db_stmt_sqlite {
200 struct db_stmt base;
201 sqlite3_stmt *sqlite;
202};
203
204static bool_Bool db_stmt_bind_sqlite(const struct db_stmt *stmt, struct db_row *rows, size_t n_rows)
205{
206 const struct db_stmt_sqlite *stmt_sqlite = (const struct db_stmt_sqlite *)stmt;
207 const struct db_row *rows_1_based = rows - 1;
208
209 for (size_t row = 1; row <= n_rows; row++) {
210 const struct db_row *r = &rows_1_based[row];
211 if (r->kind == '\0') break;
212
213 if (r->kind == 's') {
214 if (sqlite3_bind_text(stmt_sqlite->sqlite, (int)row, r->u.s, -1, NULL((void*)0)) != SQLITE_OK0)
215 return false0;
216 } else if (r->kind == 'i') {
217 if (sqlite3_bind_int(stmt_sqlite->sqlite, (int)row, r->u.i) != SQLITE_OK0)
218 return false0;
219 } else {
220 return false0;
221 }
222 }
223
224 return true1;
225}
226
227static bool_Bool db_stmt_step_sqlite(const struct db_stmt *stmt, struct db_row *row)
228{
229 const struct db_stmt_sqlite *stmt_sqlite = (const struct db_stmt_sqlite *)stmt;
230
231 if (sqlite3_step(stmt_sqlite->sqlite) != SQLITE_ROW100)
232 return false0;
233
234 int column_id = 0;
235 for (struct db_row *r = row; r->kind != '\0'; r++, column_id++) {
236 if (r->kind == 'i') {
237 r->u.i = sqlite3_column_int(stmt_sqlite->sqlite, column_id);
238 } else if (r->kind == 's') {
239 r->u.s = (char *)sqlite3_column_text(stmt_sqlite->sqlite, column_id);
240 } else {
241 return false0;
242 }
243 }
244
245 return true1;
246}
247
248static void db_stmt_finalize_sqlite(struct db_stmt *stmt)
249{
250 struct db_stmt_sqlite *stmt_sqlite = (struct db_stmt_sqlite *)stmt;
251
252 sqlite3_finalize(stmt_sqlite->sqlite);
253 free(stmt_sqlite);
254}
255
256static struct db_stmt *db_prepare_sqlite(const struct db *db, const char *sql,
257 const size_t sql_len)
258{
259 const struct db_sqlite *db_sqlite = (const struct db_sqlite *)db;
260 struct db_stmt_sqlite *stmt_sqlite = malloc(sizeof(*stmt_sqlite));
261
262 if (!stmt_sqlite)
263 return NULL((void*)0);
264
265 int ret = sqlite3_prepare(db_sqlite->sqlite, sql, (int)sql_len, &stmt_sqlite->sqlite, NULL((void*)0));
266 if (ret != SQLITE_OK0) {
267 free(stmt_sqlite);
268 return NULL((void*)0);
269 }
270
271 stmt_sqlite->base.bind = db_stmt_bind_sqlite;
272 stmt_sqlite->base.step = db_stmt_step_sqlite;
273 stmt_sqlite->base.finalize = db_stmt_finalize_sqlite;
274
275 return (struct db_stmt *)stmt_sqlite;
276}
277
278static void db_disconnect_sqlite(struct db *db)
279{
280 struct db_sqlite *db_sqlite = (struct db_sqlite *)db;
281
282 sqlite3_close(db_sqlite->sqlite);
283 free(db);
284}
285
286struct db *db_connect_sqlite(const char *path, bool_Bool read_only, const char *pragmas[])
287{
288 struct db_sqlite *db_sqlite = malloc(sizeof(*db_sqlite));
289
290 if (!db_sqlite)
291 return NULL((void*)0);
292
293 int flags = read_only ? SQLITE_OPEN_READONLY0x00000001 : 0;
294 int ret = sqlite3_open_v2(path, &db_sqlite->sqlite, flags, NULL((void*)0));
295 if (ret != SQLITE_OK0) {
296 free(db_sqlite);
297 return NULL((void*)0);
298 }
299
300 if (pragmas) {
301 for (size_t p = 0; pragmas[p]; p++)
302 sqlite3_exec(db_sqlite->sqlite, pragmas[p], NULL((void*)0), NULL((void*)0), NULL((void*)0));
303 }
304
305 db_sqlite->base.disconnect = db_disconnect_sqlite;
306 db_sqlite->base.prepare = db_prepare_sqlite;
307
308 return (struct db *)db_sqlite;
309}