mirror of
				https://github.com/isar/rusqlite.git
				synced 2025-10-31 22:08:55 +08:00 
			
		
		
		
	Fix panic at 'SQLite API not initialized or SQLite feature omitted'
`to_sqlite_error` needs `sqlite3_malloc` ``` sqlite> .log on sqlite> .load target/debug/examples/libloadable_extension.so Error: error during initialization: SQLite version mismatch: 3014000 < 3042000 ```
This commit is contained in:
		| @@ -25,7 +25,9 @@ pub extern "C" fn sqlite3_extension_init( | |||||||
|     pz_err_msg: *mut *mut c_char, |     pz_err_msg: *mut *mut c_char, | ||||||
|     p_api: *mut ffi::sqlite3_api_routines, |     p_api: *mut ffi::sqlite3_api_routines, | ||||||
| ) -> c_int { | ) -> c_int { | ||||||
|     if let Err(err) = extension_init(db, p_api) { |     if p_api.is_null() { | ||||||
|  |         return ffi::SQLITE_ERROR; | ||||||
|  |     } else if let Err(err) = extension_init(db, p_api) { | ||||||
|         return unsafe { to_sqlite_error(&err, pz_err_msg) }; |         return unsafe { to_sqlite_error(&err, pz_err_msg) }; | ||||||
|     } |     } | ||||||
|     ffi::SQLITE_OK |     ffi::SQLITE_OK | ||||||
|   | |||||||
| @@ -6267,9 +6267,7 @@ pub unsafe fn sqlite3_expanded_sql( | |||||||
| pub unsafe fn rusqlite_extension_init2( | pub unsafe fn rusqlite_extension_init2( | ||||||
|     p_api: *mut sqlite3_api_routines, |     p_api: *mut sqlite3_api_routines, | ||||||
| ) -> ::std::result::Result<(), crate::InitError> { | ) -> ::std::result::Result<(), crate::InitError> { | ||||||
|     if p_api.is_null() { |     __SQLITE3_MALLOC.store((*p_api).malloc, ::atomic::Ordering::Release); | ||||||
|         return Err(crate::InitError::NullApiPointer); |  | ||||||
|     } |  | ||||||
|     if let Some(fun) = (*p_api).libversion_number { |     if let Some(fun) = (*p_api).libversion_number { | ||||||
|         let version = fun(); |         let version = fun(); | ||||||
|         if SQLITE_VERSION_NUMBER > version { |         if SQLITE_VERSION_NUMBER > version { | ||||||
| @@ -6371,7 +6369,6 @@ pub unsafe fn rusqlite_extension_init2( | |||||||
|     __SQLITE3_LIBVERSION.store((*p_api).libversion, ::atomic::Ordering::Release); |     __SQLITE3_LIBVERSION.store((*p_api).libversion, ::atomic::Ordering::Release); | ||||||
|     __SQLITE3_LIBVERSION_NUMBER |     __SQLITE3_LIBVERSION_NUMBER | ||||||
|         .store((*p_api).libversion_number, ::atomic::Ordering::Release); |         .store((*p_api).libversion_number, ::atomic::Ordering::Release); | ||||||
|     __SQLITE3_MALLOC.store((*p_api).malloc, ::atomic::Ordering::Release); |  | ||||||
|     __SQLITE3_OPEN.store((*p_api).open, ::atomic::Ordering::Release); |     __SQLITE3_OPEN.store((*p_api).open, ::atomic::Ordering::Release); | ||||||
|     __SQLITE3_OPEN16.store((*p_api).open16, ::atomic::Ordering::Release); |     __SQLITE3_OPEN16.store((*p_api).open16, ::atomic::Ordering::Release); | ||||||
|     __SQLITE3_PREPARE.store((*p_api).prepare, ::atomic::Ordering::Release); |     __SQLITE3_PREPARE.store((*p_api).prepare, ::atomic::Ordering::Release); | ||||||
|   | |||||||
| @@ -702,6 +702,7 @@ mod loadable_extension { | |||||||
|         let sqlite3_api_routines_ident = sqlite3_api_routines.ident; |         let sqlite3_api_routines_ident = sqlite3_api_routines.ident; | ||||||
|         let p_api = quote::format_ident!("p_api"); |         let p_api = quote::format_ident!("p_api"); | ||||||
|         let mut stores = Vec::new(); |         let mut stores = Vec::new(); | ||||||
|  |         let mut malloc = Vec::new(); | ||||||
|         // (2) `#define sqlite3_xyz sqlite3_api->abc` => `pub unsafe fn |         // (2) `#define sqlite3_xyz sqlite3_api->abc` => `pub unsafe fn | ||||||
|         // sqlite3_xyz(args) -> ty {...}` for each `abc` field: |         // sqlite3_xyz(args) -> ty {...}` for each `abc` field: | ||||||
|         for field in sqlite3_api_routines.fields { |         for field in sqlite3_api_routines.fields { | ||||||
| @@ -764,7 +765,12 @@ mod loadable_extension { | |||||||
|                 &syn::parse2(tokens).expect("could not parse quote output"), |                 &syn::parse2(tokens).expect("could not parse quote output"), | ||||||
|             )); |             )); | ||||||
|             output.push('\n'); |             output.push('\n'); | ||||||
|             stores.push(quote::quote! { |             if name == "malloc" { | ||||||
|  |                 &mut malloc | ||||||
|  |             } else { | ||||||
|  |                 &mut stores | ||||||
|  |             } | ||||||
|  |             .push(quote::quote! { | ||||||
|                 #ptr_name.store( |                 #ptr_name.store( | ||||||
|                     (*#p_api).#ident, |                     (*#p_api).#ident, | ||||||
|                     ::atomic::Ordering::Release, |                     ::atomic::Ordering::Release, | ||||||
| @@ -775,9 +781,7 @@ mod loadable_extension { | |||||||
|         let tokens = quote::quote! { |         let tokens = quote::quote! { | ||||||
|             /// Like SQLITE_EXTENSION_INIT2 macro |             /// Like SQLITE_EXTENSION_INIT2 macro | ||||||
|             pub unsafe fn rusqlite_extension_init2(#p_api: *mut #sqlite3_api_routines_ident) -> ::std::result::Result<(),crate::InitError> { |             pub unsafe fn rusqlite_extension_init2(#p_api: *mut #sqlite3_api_routines_ident) -> ::std::result::Result<(),crate::InitError> { | ||||||
|                 if #p_api.is_null() { |                 #(#malloc)* // sqlite3_malloc needed by to_sqlite_error | ||||||
|                     return Err(crate::InitError::NullApiPointer); |  | ||||||
|                 } |  | ||||||
|                 if let Some(fun) = (*#p_api).libversion_number { |                 if let Some(fun) = (*#p_api).libversion_number { | ||||||
|                     let version = fun(); |                     let version = fun(); | ||||||
|                     if SQLITE_VERSION_NUMBER > version { |                     if SQLITE_VERSION_NUMBER > version { | ||||||
|   | |||||||
| @@ -7463,9 +7463,7 @@ pub unsafe fn sqlite3_is_interrupted(arg1: *mut sqlite3) -> ::std::os::raw::c_in | |||||||
| pub unsafe fn rusqlite_extension_init2( | pub unsafe fn rusqlite_extension_init2( | ||||||
|     p_api: *mut sqlite3_api_routines, |     p_api: *mut sqlite3_api_routines, | ||||||
| ) -> ::std::result::Result<(), crate::InitError> { | ) -> ::std::result::Result<(), crate::InitError> { | ||||||
|     if p_api.is_null() { |     __SQLITE3_MALLOC.store((*p_api).malloc, ::atomic::Ordering::Release); | ||||||
|         return Err(crate::InitError::NullApiPointer); |  | ||||||
|     } |  | ||||||
|     if let Some(fun) = (*p_api).libversion_number { |     if let Some(fun) = (*p_api).libversion_number { | ||||||
|         let version = fun(); |         let version = fun(); | ||||||
|         if SQLITE_VERSION_NUMBER > version { |         if SQLITE_VERSION_NUMBER > version { | ||||||
| @@ -7567,7 +7565,6 @@ pub unsafe fn rusqlite_extension_init2( | |||||||
|     __SQLITE3_LIBVERSION.store((*p_api).libversion, ::atomic::Ordering::Release); |     __SQLITE3_LIBVERSION.store((*p_api).libversion, ::atomic::Ordering::Release); | ||||||
|     __SQLITE3_LIBVERSION_NUMBER |     __SQLITE3_LIBVERSION_NUMBER | ||||||
|         .store((*p_api).libversion_number, ::atomic::Ordering::Release); |         .store((*p_api).libversion_number, ::atomic::Ordering::Release); | ||||||
|     __SQLITE3_MALLOC.store((*p_api).malloc, ::atomic::Ordering::Release); |  | ||||||
|     __SQLITE3_OPEN.store((*p_api).open, ::atomic::Ordering::Release); |     __SQLITE3_OPEN.store((*p_api).open, ::atomic::Ordering::Release); | ||||||
|     __SQLITE3_OPEN16.store((*p_api).open16, ::atomic::Ordering::Release); |     __SQLITE3_OPEN16.store((*p_api).open16, ::atomic::Ordering::Release); | ||||||
|     __SQLITE3_PREPARE.store((*p_api).prepare, ::atomic::Ordering::Release); |     __SQLITE3_PREPARE.store((*p_api).prepare, ::atomic::Ordering::Release); | ||||||
|   | |||||||
| @@ -275,8 +275,6 @@ pub fn code_to_str(code: c_int) -> &'static str { | |||||||
| #[derive(Clone, Copy, Debug, PartialEq, Eq)] | #[derive(Clone, Copy, Debug, PartialEq, Eq)] | ||||||
| #[non_exhaustive] | #[non_exhaustive] | ||||||
| pub enum InitError { | pub enum InitError { | ||||||
|     /// Invalid sqlite3_api_routines pointer |  | ||||||
|     NullApiPointer, |  | ||||||
|     /// Version mismatch between the extension and the SQLite3 library |     /// Version mismatch between the extension and the SQLite3 library | ||||||
|     VersionMismatch { compile_time: i32, runtime: i32 }, |     VersionMismatch { compile_time: i32, runtime: i32 }, | ||||||
|     /// Invalid function pointer in one of sqlite3_api_routines fields |     /// Invalid function pointer in one of sqlite3_api_routines fields | ||||||
| @@ -286,9 +284,6 @@ pub enum InitError { | |||||||
| impl ::std::fmt::Display for InitError { | impl ::std::fmt::Display for InitError { | ||||||
|     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { |     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { | ||||||
|         match *self { |         match *self { | ||||||
|             InitError::NullApiPointer => { |  | ||||||
|                 write!(f, "Invalid sqlite3_api_routines pointer") |  | ||||||
|             } |  | ||||||
|             InitError::VersionMismatch { |             InitError::VersionMismatch { | ||||||
|                 compile_time, |                 compile_time, | ||||||
|                 runtime, |                 runtime, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user