I am attempting to write a png to a SQLite3 database in C#. I have managed to correctly import the external DLL function sqlite3_bind_blob thanks to the answer here. But now I am getting an error when I write the image to my SQLite3 database.
Can you tell me what I am doing wrong? The function function sqlite3_bind_blob is returning the error 21 - SQLITE_MISMATCH 20 - Data type mismatch. I am unsure what exactly is going wrong.
Heres my code:
string query = string.Format("INSERT OR REPLACE INTO myTable(lat, lon, image) VALUES({0}, {1}, ?1);", lat, lon);
if (sqlite3_prepare_v2 (_connection, query, query.Length, out stmHandle, IntPtr.Zero) != SQLITE_OK) {
IntPtr errorMsg = sqlite3_errmsg (_connection);
throw new SqliteException (Marshal.PtrToStringAnsi (errorMsg));
}
IntPtr SQLITE_TRANSIENT = new IntPtr(-1); // Represents SQLITE_TRANSIENT
int res = sqlite3_bind_blob (stmHandle, 1, blob, blob.Length, SQLITE_TRANSIENT);
// res always equals 21
From my debugging I know that the blob correctly contains valid png data because I can write it out to a file and open that file. I also know that the length of the blob is correct aswell. Maybe its my query string INSERT OR REPLACE INTO myTable(lat, lon, image) VALUES({0}, {1}, ?1);?
You are mixing managed with unmanaged code.
int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
You are providing managed IntPtr blob instead of unmanaged const void*blob.
You should be very sure about what you're doing when mixing managed with unmanaged code - and it seam you're not...
You may workaround this situation something like this (I don't have compiler right now) using:
unsafe { //this is for C#... probably not needed in C++/CLI
int res = sqlite3_bind_blob (stmHandle, 1, (const void*) blob.ToPointer(), (int) blob.Length, SQLITE_TRANSIENT);
}
Anyways, unless you're pretty sure you need this stuff, I recommend you to go on managed system.data.sqlite and abandon SQLite3 CAPI.
Related
Below is the code snippet:
I am trying to upload a file having long as a datatype and storing that file size in a byte array.
long fileSize = uploadedFile.getSize();
byte techGuide[] = new byte[fileSize];
I got the build error:
error: incompatible types: possible lossy conversion from long to int
Please suggest what i am missing and what should i try?
Path path = uploadedFile.toPath(); // File.toPath.
Repair of your code:
// Not needed for readAllBytes.
long fileSize = Files.size(path);
if (fileSize > Integer.MAX) {
throw new IllegalArgumentException("File too large");
}
byte[] techGuide = new byte[(int)fileSize];
New code:
byte[] techGuide = Files.readAllBytes(path);
Arrays are limited by their int index. You would need to cast the fileSize to an int (and check an overflow). However Files.readAllBytes does that for you, throwing an OutOfMemoryError of > Integer.MAX - 8.
I am trying to configure SQLite to run on an embedded system (ARM® Cortex®-M7). I have downloaded the amalgamation from the SQLite website, imported it into the project, and added the following symbols: SQLITE_THREADSAFE=0, SQLITE_OS_OTHER=1, SQLITE_OMIT_WAL=1 to allow it to compile.
I then downloaded test_onefile.c (available here: http://www.sqlite.org/vfs.html) which is supposed to allow SQLite to operate directly on embedded media without using an intermediate filesystem and imported it into the project (I was also sure to provide an sqlite3_os_init() function to register the VFS).
SQLITE_API int sqlite3_os_init(void)
{
extern int fs_register(void);
return fs_register();
}
In a separate file fs_register() looks like this:
/*
** This procedure registers the fs vfs with SQLite. If the argument is
** true, the fs vfs becomes the new default vfs. It is the only publicly
** available function in this file.
*/
int fs_register(void)
{
if (fs_vfs.pParent) return SQLITE_OK;
fs_vfs.pParent = sqlite3_vfs_find(0);
fs_vfs.base.mxPathname = fs_vfs.pParent->mxPathname;
fs_vfs.base.szOsFile = MAX(sizeof(tmp_file), sizeof(fs_file));
return sqlite3_vfs_register(&fs_vfs.base, 0);
}
I can successfully register a filesystem, open a database, and prepare SQL statements using sqlite3_register_vfs(), sqlite3_open(), and sqlite3_prepare().
When opening a database I am sure to use the ":memory:" string to create the database in memory rather than as a file.
static void TestSQLiteOpenDB(void)
{
/******** setup ********************************/
sqlite3 *db;
int rc;
/******** run element/component under test *****/
rc = sqlite3_open(":memory:", &db);
sqlite3_close(db);
/******** assertion test ***********************/
TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);
}
My issue is when trying to run sqlite3_exec(). The program crashes when the following piece of code from test_onefile.c is called:
/*
** Populate the buffer pointed to by zBufOut with nByte bytes of
** random data.
*/
static int fsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut)
{
sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
return pParent->xRandomness(pParent, nByte, zBufOut);
}
If I change this function to simply return 0, it appears to work. I can then create tables, insert data into tables etc...
My question is this: Is there a need in SQLite to populate this buffer with random data or is this workaround ok? I do not want to create further headaches for myself but it was a nightmare to track this down as the point of failure and I can not quite wrap my head around what is happening.
SQLite uses this randomness for temporary files, to force changes in journal/WAL files, to generate unique column names, and when autoincremented IDs overflow.
If the returned value is constant, some of these might go into an infinite loop, so you should attempt to get actual randomness. (It does not need to be cryptographically secure.)
I'm trying to find a base pointer for UrbanTerror42.
My setup is as followed, I have a server with 2 players.
cheat-engine runs on client a.
I climb a ladder with client b and then scan for incease/decrease.
When I have found the values, I use find out what writes to this address.
But the offset are very high and point to empty memory.
I don't really know how to proceed
For the sake of clarity, I have looked up several other values and they have the same problem
I've already looked at a number of tutorials and forums, but that's always about values where the offsets are between 0 and 100 and not 80614.
I would really appreciate it if someone could tell me why this happened and what I have to do/learn to proceed.
thanks in advance
Urban Terror uses the Quake Engine. Early versions of this engine use the Quake Virtual Machine and the game logic is implemented as bytecode which is compiled into assembly by the Quake Virtual Machine. Custom allocation routines are used to load these modules into memory, relative and hardcoded offsets/addresses are created at runtime to accommodate these relocations and do not use the normal relocation table method of the portable executable file format. This is why you see these seemingly strange numbers that change every time you run the game.
The Quake Virtual Machines are file format .qvm and these qvms in memory are tracked in the QVM table. You must find the QVM table to uncover this mystery. Once you find the 2-3 QVMs and record their addresses, finding the table is easy, as you're simply doing a scan for pointers that point to these addresses and narrowing down your results by finding those which are close in memory to each other.
The QVM is defined like:
struct vmTable_t
{
vm_t vm[3];
};
struct vm_s {
// DO NOT MOVE OR CHANGE THESE WITHOUT CHANGING THE VM_OFFSET_* DEFINES
// USED BY THE ASM CODE
int programStack; // the vm may be recursively entered
intptr_t(*systemCall)(intptr_t *parms);
//------------------------------------
char name[MAX_QPATH];
// for dynamic linked modules
void *dllHandle;
intptr_t entryPoint; //(QDECL *entryPoint)(int callNum, ...);
void(*destroy)(vm_s* self);
// for interpreted modules
qboolean currentlyInterpreting;
qboolean compiled;
byte *codeBase;
int codeLength;
int *instructionPointers;
int instructionCount;
byte *dataBase;
int dataMask;
int stackBottom; // if programStack < stackBottom, error
int numSymbols;
struct vmSymbol_s *symbols;
int callLevel; // counts recursive VM_Call
int breakFunction; // increment breakCount on function entry to this
int breakCount;
BYTE *jumpTableTargets;
int numJumpTableTargets;
};
typedef struct vm_s vm_t;
The value in EAX in your original screenshot should be the same as either the codeBase or dataBase member variable of the QVM structure. The offsets are just relative to these addresses. Similarly to how you deal with ASLR, you must calculate the addresses at runtime.
Here is a truncated version of my code that does exactly this and additionally grabs important structures from memory, as an example:
void OA_t::GetVM()
{
cg = nullptr;
cgs = nullptr;
cgents = nullptr;
bLocalGame = false;
cgame = nullptr;
for (auto &vm : vmTable->vm)
{
if (strstr(vm.name, "qagame")) { bLocalGame = true; continue; }
if (strstr(vm.name, "cgame"))
{
cgame = &vm;
gamestatus = GSTAT_GAME;
//char* gamestring = Cvar_VariableString("fs_game");
switch (cgame->instructionCount)
{
case 136054: //version 88
cgents = (cg_entities*)(cgame->dataBase + 0x1649c);
cg = (cg_t*)(cgame->dataBase + 0xCC49C);
cgs = (cgs_t*)(cgame->dataBase + 0xf2720);
return;
Full source code for reference available at OpenArena Aimbot Source Code, it even includes a video overview of the code.
Full disclosure: that is a link to my website and the only viable resource I know of that covers this topic.
I do some thin wrapper of some scientific library (http://root.cern.ch) from unmanaged to managed world using C++ cli.
Reading of the special file format (which is the main goal) is implemented through:
1) Once a lifetime call of SetBranchAddress(const char name, void* outputVariable) to let it know an address of your variable
2) Than you N time call GetEntry(ulong numberOfRow) wthich fills this void* outputVariable with the appropriate value;
I put this example of usage :
double myValue; //this field will be filled
//We bind myValue to the 'column' called "x" stored in the file"
TTree->SetBranchAddress("x", &myValue);
// read first "entry" (or "row") of the file
TTree->GetEntry(0);
// from that moment myValue is filled with value of column "x" of the first row
cout<<"First entry x = "<<myValue<<endl;
TTree->GetEntry(100); //So myValue is filled with "x" of 101 row
...
So in C++/CLI code the problem is with binding managed elementary types to this void * pointer;
I have tried 3 approaches:
namespace CppLogicLibrary {
public ref class SharpToRoot
{
double mEventX;
double *mEventY;
IntPtr memEventZ;
///Constructor
SharpToRoot()
{
mEventy = new double();
memEventZ= Marshal::AllocHGlobal(sizeof(double));
}
void SetBranchAddresses()
{
pin_ptr<double> pinnedEventX = &mEventX;
mTree->SetBranchAddress("ev_x", pinnedEventX);
mTree->SetBranchAddress("ev_y", mEventY);
mTree->SetBranchAddress("ev_z", memEventZ.ToPointer());
...
//now I read some entry to test... just in place
mTree->GetEntry(100);
mTree->GetEntry(101);
double x = mEventX;
double y = *mEventY
double z = (double)Marshal::PtrToStructure(memEventZ, Double::typeid);
}
...
All of 3 variants are compiled with no errors, goes with no exceptions... BUT fills its (void *) values with some rubbish value like 5,12331E-305. In unmanaged code all works fine.
What could be the error with such void* to C++/CLI elementary types binding?
The problem was that internally data was presented by floats inside of this library. So, when it was mapped and processed as doubles on the C# side, it gave 5,12331E-305.
Each of this 3 variats worked. And, from my point of view, using of
pin_ptr pinnedEventX = &mEventX;
was improper in this case, because it doesn't persist between functions execution;
What I'm not sure, why this "float" situation was handled in native C++. As I wrote before, there wasn't any problem.
I'm working on the development of a C++ API which uses custom-designed plugins
to interface with different database engines using their APIs and specific SQL
syntax.
Currently, I'm attempting to find a way of inserting BLOBs, but since NULL is
the terminating character in C/C++, the BLOB becomes truncated when constructing
the INSERT INTO query string. So far, I've worked with
//...
char* sql;
void* blob;
int len;
//...
blob = some_blob_already_in_memory;
len = length_of_blob_already_known;
sql = sqlite3_malloc(2*len+1);
sql = sqlite3_mprintf("INSERT INTO table VALUES (%Q)", (char*)blob);
//...
I expect that, if it is at all possible to do it in the SQLite3 interactive console, it should be possible to construct the query string with properly escaped NULL characters. Maybe there's a way to do this with standard SQL which is also supported by SQLite SQL syntax?
Surely someone must have faced the same situation before. I've googled and found some answers but were in other programming languages (Python).
Thank you in advance for your feedback.
Thank you all again for your feedback. This time I'm reporting how I solved the problem with the help of the indications provided here. Hopefully this will help others in the future.
As suggested by the first three posters, I did use prepared statements — additionally because I was also interested in getting the columns' data types, and a simple sqlite3_get_table() wouldn't do.
After preparing the SQL statement in the form of the following constant string:
INSERT INTO table VALUES(?,?,?,?);
it remains the binding of the corresponding values. This is done by issuing as many sqlite3_bind_blob() calls as the columns. (I also resorted to sqlite3_bind_text() for other "simple" data types because the API I'm working on can translate integers/doubles/etc into a string). So:
#include <stdio.h>
#include <string.h>
#include <sqlite3.h>
/* ... */
void* blobvalue[4] = { NULL, NULL, NULL, NULL };
int blobsize[4] = { 0, 0, 0, 0 };
const char* tail = NULL;
const char* sql = "INSERT INTO tabl VALUES(?,?,?,?)";
sqlite3_stmt* stmt = NULL;
sqlite3* db = NULL;
/* ... */
sqlite3_open("sqlite.db", &db);
sqlite3_prepare_v2(db,
sql, strlen(sql) + 1,
&stmt, &tail);
for(unsigned int i = 0; i < 4; i++) {
sqlite3_bind_blob(stmt,
i + 1, blobvalue[i], blobsize[i],
SQLITE_TRANSIENT);
}
if(sqlite3_step(stmt) != SQLITE_DONE) {
printf("Error message: %s\n", sqlite3_errmsg(db));
}
sqlite3_finalize(stmt);
sqlite3_close(db);
Note also that some functions (sqlite3_open_v2(), sqlite3_prepare_v2()) appear on the later SQLite versions (I suppose 3.5.x and later).
The SQLite table tabl in file sqlite.db can be created with (for example)
CREATE TABLE tabl(a TEXT PRIMARY KEY, b TEXT, c TEXT, d TEXT);
You'll want to use this function with a prepared statement.
int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
In C/C++, the standard way of dealing with NULLs in strings is to either store the beginning of the string and a length, or store a pointer to the beginning of a string and one to the end of the string.
You want to precompile the statement sqlite_prepare_v2(), and then bind the blob in using sqlite3_bind_blob(). Note that the statement you bind in will be INSERT INTO table VALUES (?).