Line data Source code
1 : /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
2 : * Copyright (C) 2004-2011 Frediano Ziglio
3 : *
4 : * This library is free software; you can redistribute it and/or
5 : * modify it under the terms of the GNU Library General Public
6 : * License as published by the Free Software Foundation; either
7 : * version 2 of the License, or (at your option) any later version.
8 : *
9 : * This library is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 : * Library General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU Library General Public
15 : * License along with this library; if not, write to the
16 : * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 : * Boston, MA 02111-1307, USA.
18 : */
19 : #include <config.h>
20 :
21 : #undef NDEBUG
22 :
23 : #include <stdarg.h>
24 : #include <stdio.h>
25 :
26 : #if HAVE_STDLIB_H
27 : #include <stdlib.h>
28 : #endif /* HAVE_STDLIB_H */
29 :
30 : #if HAVE_STRING_H
31 : #include <string.h>
32 : #endif /* HAVE_STRING_H */
33 :
34 : #include <assert.h>
35 :
36 : #include <freetds/tds.h>
37 : #include <freetds/convert.h>
38 : #include <freetds/utils/string.h>
39 : #include <freetds/checks.h>
40 :
41 : #if ENABLE_EXTRA_CHECKS
42 : static void
43 7199702 : tds_check_packet_extra(const TDSPACKET * packet)
44 : {
45 7199702 : assert(packet);
46 7199702 : for (; packet; packet = packet->next) {
47 3644656 : assert(tds_packet_get_data_start(packet) == 0 || tds_packet_get_data_start(packet) == sizeof(TDS72_SMP_HEADER));
48 7199702 : assert(packet->data_len + tds_packet_get_data_start(packet) <= packet->capacity);
49 : }
50 7199702 : }
51 :
52 : void
53 3599851 : tds_check_tds_extra(const TDSSOCKET * tds)
54 : {
55 3599851 : const int invalid_state = 0;
56 : int i;
57 3599851 : TDSDYNAMIC *cur_dyn = NULL;
58 3599851 : TDSCURSOR *cur_cursor = NULL;
59 :
60 3599851 : assert(tds);
61 :
62 : /* test state and connection */
63 3599851 : switch (tds->state) {
64 : case TDS_DEAD:
65 : case TDS_WRITING:
66 : case TDS_SENDING:
67 : case TDS_PENDING:
68 : case TDS_IDLE:
69 : case TDS_READING:
70 : break;
71 : default:
72 0 : assert(invalid_state);
73 : }
74 :
75 1822328 : assert(tds->conn);
76 :
77 : #if ENABLE_ODBC_MARS
78 1822328 : assert(tds->sid < tds->conn->num_sessions);
79 1822328 : assert(tds->sid == 0 || tds->conn->mars);
80 1822328 : if (tds->state != TDS_DEAD)
81 1804704 : assert(!TDS_IS_SOCKET_INVALID(tds_get_s(tds)));
82 : #else
83 1777523 : assert(tds->state == TDS_DEAD || !TDS_IS_SOCKET_INVALID(tds_get_s(tds)));
84 1777523 : assert(tds->state != TDS_DEAD || TDS_IS_SOCKET_INVALID(tds_get_s(tds)));
85 : #endif
86 :
87 : /* test env */
88 3599851 : tds_check_env_extra(&tds->conn->env);
89 :
90 : /* test buffers and positions */
91 3599851 : assert(tds->send_packet != NULL);
92 3599851 : assert(tds->send_packet->next == NULL);
93 3599851 : tds_check_packet_extra(tds->send_packet);
94 3599851 : tds_check_packet_extra(tds->recv_packet);
95 :
96 : #if ENABLE_ODBC_MARS
97 1822328 : if (tds->conn->send_packets)
98 16538 : assert(tds->conn->send_pos <= tds->conn->send_packets->data_len + tds->conn->send_packets->data_start);
99 1822328 : if (tds->conn->recv_packet)
100 3 : assert(tds->conn->recv_pos <= tds->conn->recv_packet->data_len + tds->conn->recv_packet->data_start);
101 1822328 : if (tds->conn->mars)
102 172115 : assert(tds->send_packet->data_start == sizeof(TDS72_SMP_HEADER));
103 : else
104 1650213 : assert(tds->send_packet->data_start == 0);
105 : #endif
106 :
107 3599851 : assert(tds->in_pos <= tds->in_len);
108 3599851 : assert(tds->in_len <= tds->recv_packet->capacity);
109 : /* TODO remove blocksize from env and use out_len ?? */
110 : /* assert(tds->out_pos <= tds->out_len); */
111 : /* assert(tds->out_len == 0 || tds->out_buf != NULL); */
112 3599851 : assert(tds->send_packet->capacity >= tds->out_buf_max + TDS_ADDITIONAL_SPACE);
113 3599851 : assert(tds->out_buf == tds->send_packet->buf + tds_packet_get_data_start(tds->send_packet));
114 3599851 : assert(tds->out_buf + tds->out_buf_max + TDS_ADDITIONAL_SPACE <=
115 : tds->send_packet->buf + tds->send_packet->capacity);
116 3599851 : assert(tds->out_pos <= tds->out_buf_max + TDS_ADDITIONAL_SPACE);
117 :
118 3599851 : assert(tds->in_buf == tds->recv_packet->buf || tds->in_buf == tds->recv_packet->buf + sizeof(TDS72_SMP_HEADER));
119 3599851 : assert(tds->recv_packet->capacity > 0);
120 :
121 : /* test res_info */
122 3599851 : if (tds->res_info)
123 2165184 : tds_check_resultinfo_extra(tds->res_info);
124 :
125 : /* test num_comp_info, comp_info */
126 : assert(tds->num_comp_info >= 0);
127 4598 : for (i = 0; i < tds->num_comp_info; ++i) {
128 4598 : assert(tds->comp_info);
129 4598 : tds_check_resultinfo_extra(tds->comp_info[i]);
130 : }
131 :
132 : /* param_info */
133 3599851 : if (tds->param_info)
134 10774 : tds_check_resultinfo_extra(tds->param_info);
135 :
136 : /* test cursors */
137 3741056 : for (cur_cursor = tds->conn->cursors; cur_cursor != NULL; cur_cursor = cur_cursor->next)
138 141205 : tds_check_cursor_extra(cur_cursor);
139 :
140 : /* test dynamics */
141 3755765 : for (cur_dyn = tds->conn->dyns; cur_dyn != NULL; cur_dyn = cur_dyn->next)
142 155914 : tds_check_dynamic_extra(cur_dyn);
143 :
144 : /* test tds_ctx */
145 7199702 : tds_check_context_extra(tds_get_ctx(tds));
146 :
147 : /* TODO test char_conv_count, char_convs */
148 :
149 : /* we can't have compute and no results */
150 3599851 : assert(tds->num_comp_info == 0 || tds->res_info != NULL);
151 :
152 : /* we can't have normal and parameters results */
153 : /* TODO too strict ?? */
154 : /* assert(tds->param_info == NULL || tds->res_info == NULL); */
155 :
156 3599851 : if (tds->frozen) {
157 : TDSPACKET *pkt;
158 :
159 147532 : assert(tds->frozen_packets != NULL);
160 296522 : for (pkt = tds->frozen_packets; pkt; pkt = pkt->next) {
161 148990 : if (pkt->next == NULL)
162 147532 : assert(pkt == tds->send_packet);
163 : }
164 : } else {
165 3452319 : assert(tds->frozen_packets == NULL);
166 : }
167 3599851 : }
168 :
169 : void
170 33061 : tds_check_context_extra(const TDSCONTEXT * ctx)
171 : {
172 3632912 : assert(ctx);
173 33061 : }
174 :
175 : void
176 3599851 : tds_check_env_extra(const TDSENV * env)
177 : {
178 3599851 : assert(env);
179 :
180 3599851 : assert(env->block_size >= 0 && env->block_size <= 65536);
181 3599851 : }
182 :
183 : void
184 10219363 : tds_check_column_extra(const TDSCOLUMN * column)
185 : {
186 : int size;
187 : TDSCONNECTION conn;
188 : int varint_ok;
189 : int column_varint_size;
190 :
191 10219363 : assert(column);
192 10219363 : column_varint_size = column->column_varint_size;
193 :
194 : /* 8 is for varchar(max) or similar */
195 10219363 : assert(column_varint_size == 8 || (column_varint_size <= 5 && column_varint_size != 3));
196 :
197 10219363 : assert(column->column_scale <= column->column_prec);
198 10219363 : assert(column->column_prec <= MAXPRECISION);
199 :
200 : /* I don't like this that much... freddy77 */
201 10219363 : if (column->column_type == 0)
202 471308 : return;
203 9816086 : assert(column->funcs);
204 : assert(column->column_type > 0);
205 :
206 : /* specific checks, if true fully checked */
207 9816086 : if (column->funcs->check(column))
208 : return;
209 :
210 : /* check type and server type same or SQLNCHAR -> SQLCHAR */
211 : #define SPECIAL(ttype, server_type, varint) \
212 : if (column->column_type == ttype && column->on_server.column_type == server_type && column_varint_size == varint) {} else
213 9748055 : SPECIAL(SYBTEXT, XSYBVARCHAR, 8)
214 9747077 : SPECIAL(SYBTEXT, XSYBNVARCHAR, 8)
215 9746365 : SPECIAL(SYBIMAGE, XSYBVARBINARY, 8)
216 9746029 : assert(tds_get_cardinal_type(column->on_server.column_type, column->column_usertype) == column->column_type
217 : || (tds_get_conversion_type(column->on_server.column_type, column->column_size) == column->column_type
218 : && column_varint_size == 1 && is_fixed_type(column->column_type)));
219 :
220 9748055 : varint_ok = 0;
221 9748055 : if (column_varint_size == 8) {
222 8948 : if (column->on_server.column_type == XSYBVARCHAR
223 4474 : || column->on_server.column_type == XSYBVARBINARY
224 1674 : || column->on_server.column_type == XSYBNVARCHAR)
225 : varint_ok = 1;
226 9743581 : } else if (is_blob_type(column->column_type)) {
227 95717 : assert(column_varint_size >= 4);
228 9647864 : } else if (column->column_type == SYBVARIANT) {
229 7226 : assert(column_varint_size == 4);
230 : }
231 284 : conn.tds_version = 0x500;
232 16435749 : varint_ok = varint_ok || tds_get_varint_size(&conn, column->on_server.column_type) == column_varint_size;
233 9748055 : conn.tds_version = 0x700;
234 12804226 : varint_ok = varint_ok || tds_get_varint_size(&conn, column->on_server.column_type) == column_varint_size;
235 0 : assert(varint_ok);
236 :
237 9748055 : assert(!is_numeric_type(column->column_type));
238 9748055 : assert(column->column_cur_size <= column->column_size);
239 :
240 : /* check size of fixed type correct */
241 9748055 : size = tds_get_size_by_type(column->column_type);
242 : /* these peculiar types are variable but have only a possible size */
243 9748055 : if ((size > 0 && (column->column_type != SYBBITN && column->column_type != SYBDATEN && column->column_type != SYBTIMEN))
244 6790434 : || column->column_type == SYBVOID) {
245 : /* check macro */
246 2957657 : assert(is_fixed_type(column->column_type));
247 : /* check current size */
248 2957657 : assert(size == column->column_size);
249 : /* check cases where server need nullable types */
250 2957657 : if (column->column_type != column->on_server.column_type && (column->column_type != SYBINT8 || column->on_server.column_type != SYB5INT8)) {
251 52987 : assert(!is_fixed_type(column->on_server.column_type));
252 52987 : assert(column_varint_size == 1);
253 52987 : assert(column->column_size == column->column_cur_size || column->column_cur_size == -1);
254 : } else {
255 2904670 : assert(column_varint_size == 0
256 : || (column->column_type == SYBUNIQUE && column_varint_size == 1));
257 2904670 : assert(column->column_size == column->column_cur_size
258 : || (column->column_type == SYBUNIQUE && column->column_cur_size == -1));
259 : }
260 2957657 : assert(column->column_size == column->on_server.column_size);
261 : } else {
262 6790398 : assert(!is_fixed_type(column->column_type));
263 6790398 : assert(is_char_type(column->column_type) || (column->on_server.column_size == column->column_size || column->on_server.column_size == 0));
264 6790398 : assert(column_varint_size != 0);
265 : }
266 :
267 : /* check size of nullable types (ie intN) it's supported */
268 9748055 : if (tds_get_conversion_type(column->column_type, 4) != column->column_type) {
269 : /* check macro */
270 2197282 : assert(is_nullable_type(column->column_type));
271 : /* check that size it's correct for this type of nullable */
272 2197282 : assert(tds_get_conversion_type(column->column_type, column->column_size) != column->column_type);
273 : /* check current size */
274 2197282 : assert(column->column_size >= column->column_cur_size || column->column_cur_size == -1);
275 : /* check same type and size on server */
276 2197282 : assert(column->column_type == column->on_server.column_type);
277 2197282 : assert(column->column_size == column->on_server.column_size);
278 : }
279 9748055 : assert(column->column_iconv_left >= 0 && column->column_iconv_left <= sizeof(column->column_iconv_buf));
280 : }
281 :
282 : void
283 2311906 : tds_check_resultinfo_extra(const TDSRESULTINFO * res_info)
284 : {
285 : int i;
286 :
287 2311906 : assert(res_info);
288 : assert(res_info->num_cols >= 0);
289 2311906 : assert(res_info->ref_count > 0);
290 9065953 : for (i = 0; i < res_info->num_cols; ++i) {
291 9065953 : assert(res_info->columns);
292 9065953 : tds_check_column_extra(res_info->columns[i]);
293 9065953 : assert(res_info->columns[i]->column_data != NULL || res_info->row_size == 0);
294 : }
295 :
296 2311906 : assert(res_info->row_size >= 0);
297 :
298 : assert(res_info->computeid >= 0);
299 :
300 : assert(res_info->by_cols >= 0);
301 2311906 : assert(res_info->by_cols == 0 || res_info->bycolumns);
302 2311906 : }
303 :
304 : void
305 141205 : tds_check_cursor_extra(const TDSCURSOR * cursor)
306 : {
307 141205 : assert(cursor);
308 :
309 141205 : assert(cursor->ref_count > 0);
310 :
311 141205 : if (cursor->res_info)
312 52534 : tds_check_resultinfo_extra(cursor->res_info);
313 141205 : }
314 :
315 : void
316 160160 : tds_check_dynamic_extra(const TDSDYNAMIC * dyn)
317 : {
318 160160 : assert(dyn);
319 :
320 160160 : assert(dyn->ref_count > 0);
321 :
322 160160 : if (dyn->res_info)
323 25992 : tds_check_resultinfo_extra(dyn->res_info);
324 160160 : if (dyn->params)
325 40094 : tds_check_resultinfo_extra(dyn->params);
326 :
327 160160 : assert(!dyn->emulated || dyn->query);
328 160160 : }
329 :
330 : void
331 120701 : tds_check_freeze_extra(const TDSFREEZE * freeze)
332 : {
333 : TDSPACKET *pkt;
334 :
335 120701 : assert(freeze);
336 120701 : assert(freeze->tds != NULL);
337 120701 : assert(freeze->size_len <= 4 && freeze->size_len != 3);
338 :
339 120701 : tds_check_tds_extra(freeze->tds);
340 :
341 : /* check position */
342 120701 : if (freeze->pkt == freeze->tds->send_packet)
343 120383 : assert(freeze->tds->out_pos >= freeze->pkt_pos);
344 : else
345 318 : assert(freeze->pkt->data_len >= freeze->pkt_pos);
346 :
347 : /* check packet is in list */
348 120773 : for (pkt = freeze->tds->frozen_packets; ; pkt = pkt->next) {
349 120845 : assert(pkt);
350 120773 : if (pkt == freeze->pkt)
351 : break; /* found */
352 : }
353 120701 : }
354 :
355 : void
356 107210 : tds_extra_assert_check(const char *fn, int line, int cond, const char *cond_str)
357 : {
358 107210 : if (cond)
359 107210 : return;
360 :
361 0 : fprintf(stderr, "%s:%d: Failed checking condition '%s'\n", fn, line, cond_str);
362 :
363 0 : abort();
364 : }
365 :
366 : #endif /* ENABLE_EXTRA_CHECKS */
|