@@ -156,6 +156,31 @@ make_error_tuple(ErlNifEnv* env, const char* reason)
156
156
return enif_make_tuple2 (env , make_atom (env , "error" ), make_atom (env , reason ));
157
157
}
158
158
159
+ static ERL_NIF_TERM
160
+ make_bind_error (ErlNifEnv * env , ERL_NIF_TERM message , ERL_NIF_TERM argument )
161
+ {
162
+ assert (env );
163
+ assert (message );
164
+
165
+ ERL_NIF_TERM error_struct = enif_make_new_map (env );
166
+
167
+ enif_make_map_put (
168
+ env ,
169
+ error_struct ,
170
+ make_atom (env , "message" ),
171
+ message ,
172
+ & error_struct );
173
+
174
+ enif_make_map_put (
175
+ env ,
176
+ error_struct ,
177
+ make_atom (env , "argument" ),
178
+ argument ,
179
+ & error_struct );
180
+
181
+ return error_struct ;
182
+ }
183
+
159
184
static ERL_NIF_TERM
160
185
make_binary (ErlNifEnv * env , const void * bytes , unsigned int size )
161
186
{
@@ -173,6 +198,20 @@ make_binary(ErlNifEnv* env, const void* bytes, unsigned int size)
173
198
return term ;
174
199
}
175
200
201
+ /**
202
+ * @brief Makes a string for an error message.
203
+ *
204
+ * @note Do not use this for untrusted binaries. Intention here is to only use
205
+ * strings assembled here.
206
+ *
207
+ * @return The binary.
208
+ */
209
+ static ERL_NIF_TERM
210
+ make_message (ErlNifEnv * env , const char * str )
211
+ {
212
+ return make_binary (env , str , strlen (str ));
213
+ }
214
+
176
215
static ERL_NIF_TERM
177
216
make_sqlite3_error_tuple (ErlNifEnv * env , int rc , sqlite3 * db )
178
217
{
@@ -408,9 +447,10 @@ exqlite_prepare(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
408
447
return make_ok_tuple (env , result );
409
448
}
410
449
411
- static int
450
+ static ERL_NIF_TERM
412
451
bind (ErlNifEnv * env , const ERL_NIF_TERM arg , sqlite3_stmt * statement , int index )
413
452
{
453
+ int rc ;
414
454
int the_int ;
415
455
ErlNifSInt64 the_long_int ;
416
456
double the_double ;
@@ -419,45 +459,125 @@ bind(ErlNifEnv* env, const ERL_NIF_TERM arg, sqlite3_stmt* statement, int index)
419
459
int arity ;
420
460
const ERL_NIF_TERM * tuple ;
421
461
422
- if (enif_get_int (env , arg , & the_int )) {
423
- return sqlite3_bind_int (statement , index , the_int );
462
+ if (enif_get_int64 (env , arg , & the_long_int )) {
463
+ rc = sqlite3_bind_int64 (statement , index , the_long_int );
464
+ if (rc == SQLITE_OK ) {
465
+ return make_atom (env , "ok" );
466
+ }
467
+
468
+ return enif_raise_exception (
469
+ env ,
470
+ make_bind_error (
471
+ env ,
472
+ make_message (env , "Failed to bind argument as 64 bit integer" ),
473
+ arg ));
424
474
}
425
475
426
- if (enif_get_int64 (env , arg , & the_long_int )) {
427
- return sqlite3_bind_int64 (statement , index , the_long_int );
476
+ if (enif_get_int (env , arg , & the_int )) {
477
+ rc = sqlite3_bind_int (statement , index , the_int );
478
+ if (rc == SQLITE_OK ) {
479
+ return make_atom (env , "ok" );
480
+ }
481
+
482
+ return enif_raise_exception (
483
+ env ,
484
+ make_bind_error (
485
+ env ,
486
+ make_message (env , "Failed to bind argument as integer" ),
487
+ arg ));
428
488
}
429
489
430
490
if (enif_get_double (env , arg , & the_double )) {
431
- return sqlite3_bind_double (statement , index , the_double );
491
+ rc = sqlite3_bind_double (statement , index , the_double );
492
+ if (rc == SQLITE_OK ) {
493
+ return make_atom (env , "ok" );
494
+ }
495
+
496
+ return enif_raise_exception (
497
+ env ,
498
+ make_bind_error (
499
+ env ,
500
+ make_message (env , "Failed to bind argument as double" ),
501
+ arg ));
432
502
}
433
503
434
504
if (enif_get_atom (env , arg , the_atom , sizeof (the_atom ), ERL_NIF_LATIN1 )) {
435
505
if (0 == strcmp ("undefined" , the_atom ) || 0 == strcmp ("nil" , the_atom )) {
436
- return sqlite3_bind_null (statement , index );
506
+ rc = sqlite3_bind_null (statement , index );
507
+ if (rc == SQLITE_OK ) {
508
+ return make_atom (env , "ok" );
509
+ }
510
+
511
+ return enif_raise_exception (
512
+ env ,
513
+ make_bind_error (
514
+ env ,
515
+ make_message (env , "Failed to bind argument as null" ),
516
+ arg ));
437
517
}
438
518
439
- return sqlite3_bind_text (statement , index , the_atom , strlen (the_atom ), SQLITE_TRANSIENT );
519
+ rc = sqlite3_bind_text (statement , index , the_atom , strlen (the_atom ), SQLITE_TRANSIENT );
520
+ if (rc == SQLITE_OK ) {
521
+ return make_atom (env , "ok" );
522
+ }
523
+
524
+ return enif_raise_exception (
525
+ env ,
526
+ make_bind_error (
527
+ env ,
528
+ make_message (env , "Failed to bind argument as text" ),
529
+ arg ));
440
530
}
441
531
442
532
if (enif_inspect_iolist_as_binary (env , arg , & the_blob )) {
443
- return sqlite3_bind_text (statement , index , (char * )the_blob .data , the_blob .size , SQLITE_TRANSIENT );
533
+ rc = sqlite3_bind_text (statement , index , (char * )the_blob .data , the_blob .size , SQLITE_TRANSIENT );
534
+ if (rc == SQLITE_OK ) {
535
+ return make_atom (env , "ok" );
536
+ }
537
+
538
+ return enif_raise_exception (
539
+ env ,
540
+ make_bind_error (
541
+ env ,
542
+ make_message (env , "Failed to bind argument as text" ),
543
+ arg ));
444
544
}
445
545
446
546
if (enif_get_tuple (env , arg , & arity , & tuple )) {
447
547
if (arity != 2 ) {
448
- return -1 ;
548
+ return enif_raise_exception (
549
+ env ,
550
+ make_bind_error (
551
+ env ,
552
+ make_message (env , "Failed to bind argument as blob" ),
553
+ arg ));
449
554
}
450
555
451
556
if (enif_get_atom (env , tuple [0 ], the_atom , sizeof (the_atom ), ERL_NIF_LATIN1 )) {
452
557
if (0 == strcmp ("blob" , the_atom )) {
453
558
if (enif_inspect_iolist_as_binary (env , tuple [1 ], & the_blob )) {
454
- return sqlite3_bind_blob (statement , index , the_blob .data , the_blob .size , SQLITE_TRANSIENT );
559
+ rc = sqlite3_bind_blob (statement , index , the_blob .data , the_blob .size , SQLITE_TRANSIENT );
560
+ if (rc == SQLITE_OK ) {
561
+ return make_atom (env , "ok" );
562
+ }
563
+
564
+ return enif_raise_exception (
565
+ env ,
566
+ make_bind_error (
567
+ env ,
568
+ make_message (env , "Failed to bind argument as blob" ),
569
+ arg ));
455
570
}
456
571
}
457
572
}
458
573
}
459
574
460
- return -1 ;
575
+ return enif_raise_exception (
576
+ env ,
577
+ make_bind_error (
578
+ env ,
579
+ make_message (env , "Failed to bind argument" ),
580
+ arg ));
461
581
}
462
582
463
583
///
@@ -502,19 +622,14 @@ exqlite_bind(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
502
622
list = argv [2 ];
503
623
for (unsigned int i = 0 ; i < argument_list_length ; i ++ ) {
504
624
enif_get_list_cell (env , list , & head , & tail );
505
- int rc = bind (env , head , statement -> statement , i + 1 );
506
- if (rc == -1 ) {
507
- return enif_make_tuple2 (
508
- env ,
509
- make_atom (env , "error" ),
510
- enif_make_tuple2 (
511
- env ,
512
- make_atom (env , "wrong_type" ),
513
- head ));
514
- }
625
+ ERL_NIF_TERM result = bind (env , head , statement -> statement , i + 1 );
515
626
516
- if (rc != SQLITE_OK ) {
517
- return make_sqlite3_error_tuple (env , rc , conn -> db );
627
+ // We are going to ignore this, we have to pass it.
628
+ ERL_NIF_TERM reason ;
629
+
630
+ // Bind will set an exception if anything happens during that phase.
631
+ if (enif_has_pending_exception (env , & reason )) {
632
+ return make_error_tuple (env , "failed_to_bind_argument" );
518
633
}
519
634
520
635
list = tail ;
0 commit comments