[R-sig-DB] RSQLite, segfault in dbGetPreparedQuery() when bind.data is bad

Andrew Piskorski @tp @end|ng |rom p|@kor@k|@com
Sun Aug 21 23:10:39 CEST 2011


With RSQLite, I used dbGetPreparedQuery() to do a SQL update
statement, and passed it an incorrect bind.data data frame.  That's
clearly user error on my part, but to my surprise, it segfaulted R.

Below is a smaller example which reproduces the segfault.  Here, I've
forced my bind.df to be incorrect by simply renaming its "id" column
to something else.

Note that the segfault does not occur 100% of the time.  Often I
instead get this error:

  Error in sqliteExecStatement(con, statement, bind.data) : 
    STRING_ELT() can only be applied to a 'character vector', not a 'NULL'

But if I keep redoing the bad dbGetPreparedQuery() update statement,
within 4 or 5 tries it segfaults.  The gdb backtrace is below, here
are some highlights:

#3  0x00007fdf528765b6 in malloc_printerr (action=3, 
    str=0x7fdf52949c70 "double free or corruption (fasttop)", 
    ptr=<value optimized out>) at malloc.c:6266

#5  0x00007fdf4cfd3525 in non_select_prepared_query (
    conHandle=<value optimized out>, statement=0x0, 
    bind_data=<value optimized out>) at RS-SQLite.c:677

In the RSQLite_0.9-4.tar.gz that I'm using, line 677 of RS-SQLite.c is
the very last line of non_select_prepared_query(), which does this:

  RS_SQLite_freeParameterBinding(params);

Unfortunately I don't understand how that ParameterBinding stuff
actually works, nor what the true source of this problem is.

I am using:

  R 2.12.2 (Patched), 2011-03-18, svn.rev 55969, x86_64-unknown-linux-gnu 
  $ lsb_release -d
  Description:	Ubuntu 10.04.3 LTS
  $ uname -a
  Linux quark 2.6.32.29+drm33.13-custom #1 SMP Fri Apr 8 13:42:18 EDT 2011 x86_64 GNU/Linux

--------------------------------------------------

require("RSQLite")
handle <- dbConnect(dbDriver("SQLite") ,dbname="/data1/nobackup/andy/bad-update")
dbGetQuery(handle ,"create table atp_1 (id  INTEGER primary key  ,file_dt  REAL  ,file_length  INTEGER)")
bind.df <-
   data.frame("id"=as.integer(1:5)
              ,"file_dt"=as.POSIXct(c(paste("2010-12-0" ,1:5 ,sep="")))
              ,"file_length"=101:105 )
insert.sql <- "insert into atp_1 (id ,file_dt ,file_length) values (:id ,:file_dt ,:file_length)"
update.sql <- "update atp_1 set  file_dt = :file_dt ,file_length = :file_length  where id = :id"
dbGetPreparedQuery(handle ,insert.sql ,bind.data=bind.df)
dbGetQuery(handle ,"select count(*) from atp_1")
dbGetQuery(handle ,"select * from atp_1")
dbGetQuery(handle ,"update atp_1 set file_length = -1 where id in (2,3)")
dbGetQuery(handle ,"update atp_1 set file_dt = 0 where id in (4)")

# Oops, I forgot to include the primary key column in my bind.data:
colnames(bind.df)[1] <- "bad.id"

dbGetPreparedQuery(handle ,update.sql ,bind.data=bind.df)

# Do the dbGetPreparedQuery() update statement above repeatedly.  At
# first you will get R-level errors like this:
#    Error in sqliteExecStatement(con, statement, bind.data) : 
#      STRING_ELT() can only be applied to a 'character vector', not a 'NULL'
# Eventually you will get a segfualt.

dbDisconnect(handle) ; rm("handle")

> dbGetQuery(handle ,"select * from atp_1")
  id    file_dt file_length
1  1 1291179600         101
2  2 1291266000          -1
3  3 1291352400          -1
4  4          0         104
5  5 1291525200         105

> bind.df
  bad.id    file_dt file_length
1      1 2010-12-01         101
2      2 2010-12-02         102
3      3 2010-12-03         103
4      4 2010-12-04         104
5      5 2010-12-05         105

--------------------------------------------------

> dbGetPreparedQuery(handle ,update.sql ,bind.data=bind.df)
*** glibc detected *** /usr/local/pkg/R-2.12-branch-20110520/lib/R/bin/exec/x86_64/R: double free or corruption (fasttop): 0x0000000002887a60 ***
Process R aborted (core dumped) at Sun Aug 21 16:44:46 2011

GNU gdb (GDB) 7.1-ubuntu
Core was generated by `/usr/local/pkg/R-2.12-branch-20110520/lib/R/bin/exec/x86_64/R --no-readline'.
Program terminated with signal 6, Aborted.
(gdb) bt
#0  0x00007fdf52832a75 in *__GI_raise (sig=<value optimized out>)
    at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#1  0x00007fdf528365c0 in *__GI_abort () at abort.c:92
#2  0x00007fdf5286c4fb in __libc_message (do_abort=<value optimized out>, 
    fmt=<value optimized out>) at ../sysdeps/unix/sysv/linux/libc_fatal.c:189
#3  0x00007fdf528765b6 in malloc_printerr (action=3, 
    str=0x7fdf52949c70 "double free or corruption (fasttop)", 
    ptr=<value optimized out>) at malloc.c:6266
#4  0x00007fdf5287ce83 in *__GI___libc_free (mem=<value optimized out>)
    at malloc.c:3738
#5  0x00007fdf4cfd3525 in non_select_prepared_query (
    conHandle=<value optimized out>, statement=0x0, 
    bind_data=<value optimized out>) at RS-SQLite.c:677
#6  RS_SQLite_exec (conHandle=<value optimized out>, statement=0x0, 
    bind_data=<value optimized out>) at RS-SQLite.c:750
#7  0x00007fdf52e4b524 in do_dotcall (call=0x40203e8, 
    op=<value optimized out>, args=<value optimized out>, 
    env=<value optimized out>) at ../../../src/main/dotcode.c:847
#8  0x00007fdf52e76464 in Rf_eval (e=0x40203e8, rho=0x3d30e18)
    at ../../../src/main/eval.c:495
#9  0x00007fdf52e795bf in do_set (call=0x4020500, op=0x1dddb58, 
    args=0x40204c8, rho=0x3d30e18) at ../../../src/main/eval.c:1511
#10 0x00007fdf52e762c1 in Rf_eval (e=0x4020500, rho=0x3d30e18)
    at ../../../src/main/eval.c:469
#11 0x00007fdf52e77adc in do_begin (call=0x401db38, op=0x1ddd960, 
    args=0x4020538, rho=0x3d30e18) at ../../../src/main/eval.c:1266
#12 0x00007fdf52e762c1 in Rf_eval (e=0x401db38, rho=0x3d30e18)
    at ../../../src/main/eval.c:469
#13 0x00007fdf52e79e63 in Rf_applyClosure (call=0x401cdb0, op=0x401e008, 
    arglist=0x3d30c58, rho=0x3d30bb0, suppliedenv=0x1e04560)
    at ../../../src/main/eval.c:704
#14 0x00007fdf52e761dc in Rf_eval (e=0x401cdb0, rho=0x3d30bb0)
    at ../../../src/main/eval.c:513
#15 0x00007fdf52e795bf in do_set (call=0x401ce58, op=0x1dddb58, 
    args=0x401ce20, rho=0x3d30bb0) at ../../../src/main/eval.c:1511
#16 0x00007fdf52e762c1 in Rf_eval (e=0x401ce58, rho=0x3d30bb0)
    at ../../../src/main/eval.c:469
#17 0x00007fdf52e77adc in do_begin (call=0x401cec8, op=0x1ddd960, 
    args=0x401ce90, rho=0x3d30bb0) at ../../../src/main/eval.c:1266
#18 0x00007fdf52e762c1 in Rf_eval (e=0x401cec8, rho=0x3d30bb0)
    at ../../../src/main/eval.c:469
#19 0x00007fdf52e79e63 in Rf_applyClosure (call=0x30e8618, op=0x401b858, 
    arglist=0x3d318e8, rho=0x3d31648, suppliedenv=0x1e04560)
    at ../../../src/main/eval.c:704
#20 0x00007fdf52e761dc in Rf_eval (e=0x30e8618, rho=0x3d31648)
    at ../../../src/main/eval.c:513
#21 0x00007fdf52e77adc in do_begin (call=0x30e9270, op=0x1ddd960, 
    args=0x30e85e0, rho=0x3d31648) at ../../../src/main/eval.c:1266
#22 0x00007fdf52e762c1 in Rf_eval (e=0x30e9270, rho=0x3d31648)
    at ../../../src/main/eval.c:469
#23 0x00007fdf52e79734 in R_execClosure (call=0x3d35560, op=0x30eadb8, 
    arglist=<value optimized out>, rho=0x1e04528, newrho=0x3d31648)
    at ../../../src/main/eval.c:790
#24 0x00007fdf52e79ad6 in R_execMethod (op=0x30eadb8, rho=0x3d35800)
    at ../../../src/main/eval.c:893
#25 0x00007fdf50f1aef2 in R_dispatchGeneric (fname=0x26b4c98, ev=0x3d35800, 
    fdef=0x3d34908)
    at ../../../../../src/library/methods/src/methods_list_dispatch.c:994
#26 0x00007fdf52eb8305 in do_standardGeneric (call=0x0, 
    op=<value optimized out>, args=0x3d34908, env=0x3d35800)
    at ../../../src/main/objects.c:1046
#27 0x00007fdf52e763ad in Rf_eval (e=0x31bdc10, rho=0x3d35800)
    at ../../../src/main/eval.c:498
#28 0x00007fdf52e79e63 in Rf_applyClosure (call=0x3d35560, op=0x2c64010, 
    arglist=0x3d35608, rho=0x1e04528, suppliedenv=0x1e04560)
    at ../../../src/main/eval.c:704
#29 0x00007fdf52e761dc in Rf_eval (e=0x3d35560, rho=0x1e04528)
    at ../../../src/main/eval.c:513
#30 0x00007fdf52ea6ec7 in Rf_ReplIteration (rho=0x1e04528, 
    savestack=<value optimized out>, browselevel=0, state=0x7fff8007bb80)
    at ../../../src/main/main.c:262
#31 0x00007fdf52ea71b0 in R_ReplConsole (rho=0x1e04528, savestack=0, 
    browselevel=0) at ../../../src/main/main.c:311
#32 0x00007fdf52ea76a0 in run_Rmainloop () at ../../../src/main/main.c:1004
#33 0x000000000040088b in main (ac=<value optimized out>, 
    av=<value optimized out>) at ../../../src/main/Rmain.c:32
#34 0x00007fdf5281dc4d in __libc_start_main (main=<value optimized out>, 
    argc=<value optimized out>, ubp_av=<value optimized out>, 
    init=<value optimized out>, fini=<value optimized out>, 
    rtld_fini=<value optimized out>, stack_end=0x7fff8007ccb8)
    at libc-start.c:226
#35 0x00000000004007a9 in _start ()
(gdb) q

-- 
Andrew Piskorski <atp using piskorski.com>




More information about the R-sig-DB mailing list