1
votes

In the test program:

#include <sqlite3.h>
#include <stdio.h>
#include <stdlib.h>

int     main(void) 
{
   sqlite3        *conn;
   sqlite3_stmt   *res;
   int            rc          =   0;
   int            rec_count   =   0;
   const char     *errMSG;
   const char     *tail;
   const char     *sql;

   rc = sqlite3_open("ljdata.sl3", &conn);
   if (rc) 
   {   puts("Can not open database");
      exit(0);
   }
   printf ("database open\n");

   sql   =   "create table if not exists people (id int, firstname varchar(20), lastname varchar(20), phonenumber char(10))";
   rc   =   sqlite3_exec(conn, sql, 0, 0, 0);
   if   (rc != SQLITE_OK)
   {   printf   ("Cannot access table, rc = %d,\n%s\n", rc, sqlite3_errmsg (conn));
      printf   ("sql = %s", sql);
      return   -2;
   }
   printf("db table (?)created\n");

   rc = sqlite3_exec(conn,
               "update people set phonenumber=\'5055559999\' where id=3",
               0, 0, 0);
   //printf ("1st update done with rc = %d\n", rc);

   rc = sqlite3_prepare_v2(conn,
               "select lastname,firstname,phonenumber,id from people order by id",
               1000, &res, &tail);
   printf ("prepare statement executed\n");

   if (rc != SQLITE_OK) 
   {   puts("We did not get any data!");
      exit(0);
   }

   puts("==========================");

   while (sqlite3_step(res) == SQLITE_ROW) 
   {   printf("%s|", sqlite3_column_text(res, 0));
      printf("%s|", sqlite3_column_text(res, 1));
      printf("%s|", sqlite3_column_text(res, 2));
      printf("%u\n", sqlite3_column_int(res, 3));

      rec_count++;
   }

   puts("==========================");
   printf("We received %d records.\n", rec_count);

   sqlite3_finalize(res);

   sqlite3_close(conn);

   return 0;
}

if I comment out:
printf ("1st update done with rc = %d\n", rc); // <<== THIS STATEMENT
I get a segment fault. Otherwise I appear to get a normal completion. gcc -v -->
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.7/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian 4.7.2-5' --with-bugurl=file:///usr/share/doc/gcc-4.7/README.Bugs --enable-languages=c,c++,go,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.7 --enable-shared --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.7 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --enable-plugin --enable-objc-gc --with-arch-32=i586 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.7.2 (Debian 4.7.2-5)

However, I also get a (less analyzed) segment fault on Debian testing.
Any suggestions? (I note that a similar error was answered by "You need to allocate space for the sql string, but I'm using a literal, so that shouldn't apply.)

1

1 Answers

1
votes

Off the top of my head, the sqlite3_prepare_v2 call fails because you lie about the string length:

rc = sqlite3_prepare_v2(conn,
           "select lastname,firstname,phonenumber,id from people order by id",
           1000, &res, &tail);

It appears to work if you include the printf call because the string literal will be placed in the same section as the string who's length you lie about, and whatever sqlite3_prepare_v2 is doing just spills over the other string.

What you have here is effectively a buffer overrun.