LCOV - code coverage report
Current view: top level - src/tds - tds_checks.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 157 161 97.5 %
Date: 2024-04-18 21:21:48 Functions: 10 10 100.0 %

          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     7098166 : tds_check_packet_extra(const TDSPACKET * packet)
      44             : {
      45     7098166 :         assert(packet);
      46     7098166 :         for (; packet; packet = packet->next) {
      47     3596750 :                 assert(tds_packet_get_data_start(packet) == 0 || tds_packet_get_data_start(packet) == sizeof(TDS72_SMP_HEADER));
      48     7098166 :                 assert(packet->data_len + tds_packet_get_data_start(packet) <= packet->capacity);
      49             :         }
      50     7098166 : }
      51             : 
      52             : void
      53     3549083 : tds_check_tds_extra(const TDSSOCKET * tds)
      54             : {
      55     3549083 :         const int invalid_state = 0;
      56             :         int i;
      57     3549083 :         TDSDYNAMIC *cur_dyn = NULL;
      58     3549083 :         TDSCURSOR *cur_cursor = NULL;
      59             : 
      60     3549083 :         assert(tds);
      61             : 
      62             :         /* test state and connection */
      63     3549083 :         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     1798375 :         assert(tds->conn);
      76             : 
      77             : #if ENABLE_ODBC_MARS
      78     1798375 :         assert(tds->sid < tds->conn->num_sessions);
      79     1798375 :         assert(tds->sid == 0 || tds->conn->mars);
      80     1798375 :         if (tds->state != TDS_DEAD)
      81     1780751 :                 assert(!TDS_IS_SOCKET_INVALID(tds_get_s(tds)));
      82             : #else
      83     1750708 :         assert(tds->state == TDS_DEAD || !TDS_IS_SOCKET_INVALID(tds_get_s(tds)));
      84     1750708 :         assert(tds->state != TDS_DEAD || TDS_IS_SOCKET_INVALID(tds_get_s(tds)));
      85             : #endif
      86             : 
      87             :         /* test env */
      88     3549083 :         tds_check_env_extra(&tds->conn->env);
      89             : 
      90             :         /* test buffers and positions */
      91     3549083 :         assert(tds->send_packet != NULL);
      92     3549083 :         assert(tds->send_packet->next == NULL);
      93     3549083 :         tds_check_packet_extra(tds->send_packet);
      94     3549083 :         tds_check_packet_extra(tds->recv_packet);
      95             : 
      96             : #if ENABLE_ODBC_MARS
      97     1798375 :         if (tds->conn->send_packets)
      98       16520 :                 assert(tds->conn->send_pos <= tds->conn->send_packets->data_len + tds->conn->send_packets->data_start);
      99     1798375 :         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     1798375 :         if (tds->conn->mars)
     102      172011 :                 assert(tds->send_packet->data_start == sizeof(TDS72_SMP_HEADER));
     103             :         else
     104     1626364 :                 assert(tds->send_packet->data_start == 0);
     105             : #endif
     106             : 
     107     3549083 :         assert(tds->in_pos <= tds->in_len);
     108     3549083 :         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     3549083 :         assert(tds->send_packet->capacity >= tds->out_buf_max + TDS_ADDITIONAL_SPACE);
     113     3549083 :         assert(tds->out_buf == tds->send_packet->buf + tds_packet_get_data_start(tds->send_packet));
     114     3549083 :         assert(tds->out_buf + tds->out_buf_max + TDS_ADDITIONAL_SPACE <=
     115             :                 tds->send_packet->buf + tds->send_packet->capacity);
     116     3549083 :         assert(tds->out_pos <= tds->out_buf_max + TDS_ADDITIONAL_SPACE);
     117             : 
     118     3549083 :         assert(tds->in_buf == tds->recv_packet->buf || tds->in_buf == tds->recv_packet->buf + sizeof(TDS72_SMP_HEADER));
     119     3549083 :         assert(tds->recv_packet->capacity > 0);
     120             : 
     121             :         /* test res_info */
     122     3549083 :         if (tds->res_info)
     123     2117192 :                 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     3549083 :         if (tds->param_info)
     134       10774 :                 tds_check_resultinfo_extra(tds->param_info);
     135             : 
     136             :         /* test cursors */
     137     3690288 :         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     3704997 :         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     7098166 :         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     3549083 :         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     3549083 :         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     3401551 :                 assert(tds->frozen_packets == NULL);
     166             :         }
     167     3549083 : }
     168             : 
     169             : void
     170       33061 : tds_check_context_extra(const TDSCONTEXT * ctx)
     171             : {
     172     3582144 :         assert(ctx);
     173       33061 : }
     174             : 
     175             : void
     176     3549083 : tds_check_env_extra(const TDSENV * env)
     177             : {
     178     3549083 :         assert(env);
     179             : 
     180     3549083 :         assert(env->block_size >= 0 && env->block_size <= 65536);
     181     3549083 : }
     182             : 
     183             : void
     184     9893981 : 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     9893981 :         assert(column);
     192     9893981 :         column_varint_size = column->column_varint_size;
     193             : 
     194             :         /* 8 is for varchar(max) or similar */
     195     9893981 :         assert(column_varint_size == 8 || (column_varint_size <= 5 && column_varint_size != 3));
     196             : 
     197     9893981 :         assert(column->column_scale <= column->column_prec);
     198     9893981 :         assert(column->column_prec <= MAXPRECISION);
     199             : 
     200             :         /* I don't like this that much... freddy77 */
     201     9893981 :         if (column->column_type == 0)
     202      474132 :                 return;
     203     9487880 :         assert(column->funcs);
     204             :         assert(column->column_type > 0);
     205             : 
     206             :         /* specific checks, if true fully checked */
     207     9487880 :         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     9419849 :         SPECIAL(SYBTEXT, XSYBVARCHAR, 8)
     214     9418871 :         SPECIAL(SYBTEXT, XSYBNVARCHAR, 8)
     215     9418159 :         SPECIAL(SYBIMAGE, XSYBVARBINARY, 8)
     216     9417823 :         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     9419849 :         varint_ok = 0;
     221     9419849 :         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     9415375 :         } else if (is_blob_type(column->column_type)) {
     227       93599 :                 assert(column_varint_size >= 4);
     228     9321776 :         } else if (column->column_type == SYBVARIANT) {
     229        7226 :                 assert(column_varint_size == 4);
     230             :         }
     231         284 :         conn.tds_version = 0x500;
     232    15931017 :         varint_ok = varint_ok || tds_get_varint_size(&conn, column->on_server.column_type) == column_varint_size;
     233     9419849 :         conn.tds_version = 0x700;
     234    12324340 :         varint_ok = varint_ok || tds_get_varint_size(&conn, column->on_server.column_type) == column_varint_size;
     235           0 :         assert(varint_ok);
     236             : 
     237     9419849 :         assert(!is_numeric_type(column->column_type));
     238     9419849 :         assert(column->column_cur_size <= column->column_size);
     239             : 
     240             :         /* check size of fixed type correct */
     241     9419849 :         size = tds_get_size_by_type(column->column_type);
     242             :         /* these peculiar types are variable but have only a possible size */
     243     9419849 :         if ((size > 0 && (column->column_type != SYBBITN && column->column_type != SYBDATEN && column->column_type != SYBTIMEN))
     244     6475544 :             || column->column_type == SYBVOID) {
     245             :                 /* check macro */
     246     2944341 :                 assert(is_fixed_type(column->column_type));
     247             :                 /* check current size */
     248     2944341 :                 assert(size == column->column_size);
     249             :                 /* check cases where server need nullable types */
     250     2944341 :                 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     2891354 :                         assert(column_varint_size == 0
     256             :                                 || (column->column_type == SYBUNIQUE && column_varint_size == 1));
     257     2891354 :                         assert(column->column_size == column->column_cur_size
     258             :                                 || (column->column_type == SYBUNIQUE && column->column_cur_size == -1));
     259             :                 }
     260     2944341 :                 assert(column->column_size == column->on_server.column_size);
     261             :         } else {
     262     6475508 :                 assert(!is_fixed_type(column->column_type));
     263     6475508 :                 assert(is_char_type(column->column_type) || (column->on_server.column_size == column->column_size || column->on_server.column_size == 0));
     264     6475508 :                 assert(column_varint_size != 0);
     265             :         }
     266             : 
     267             :         /* check size of nullable types (ie intN) it's supported */
     268     9419849 :         if (tds_get_conversion_type(column->column_type, 4) != column->column_type) {
     269             :                 /* check macro */
     270     2044342 :                 assert(is_nullable_type(column->column_type));
     271             :                 /* check that size it's correct for this type of nullable */
     272     2044342 :                 assert(tds_get_conversion_type(column->column_type, column->column_size) != column->column_type);
     273             :                 /* check current size */
     274     2044342 :                 assert(column->column_size >= column->column_cur_size || column->column_cur_size == -1);
     275             :                 /* check same type and size on server */
     276     2044342 :                 assert(column->column_type == column->on_server.column_type);
     277     2044342 :                 assert(column->column_size == column->on_server.column_size);
     278             :         }
     279     9419849 :         assert(column->column_iconv_left >= 0 && column->column_iconv_left <= sizeof(column->column_iconv_buf));
     280             : }
     281             : 
     282             : void
     283     2263914 : tds_check_resultinfo_extra(const TDSRESULTINFO * res_info)
     284             : {
     285             :         int i;
     286             : 
     287     2263914 :         assert(res_info);
     288             :         assert(res_info->num_cols >= 0);
     289     2263914 :         assert(res_info->ref_count > 0);
     290     8764672 :         for (i = 0; i < res_info->num_cols; ++i) {
     291     8764672 :                 assert(res_info->columns);
     292     8764672 :                 tds_check_column_extra(res_info->columns[i]);
     293     8764672 :                 assert(res_info->columns[i]->column_data != NULL || res_info->row_size == 0);
     294             :         }
     295             : 
     296     2263914 :         assert(res_info->row_size >= 0);
     297             : 
     298             :         assert(res_info->computeid >= 0);
     299             : 
     300             :         assert(res_info->by_cols >= 0);
     301     2263914 :         assert(res_info->by_cols == 0 || res_info->bycolumns);
     302     2263914 : }
     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 */

Generated by: LCOV version 1.13