We have a simple stored procedure call to DB2, where one of the parameters is a BINARY output parameter. We have tried both leaving the Data as the default string type and setting it to a Buffer; in both cases, node crashes due to a double memory free. This bug report is for the case of using a Buffer type. I opened #943 for non-Buffer types (since it's a different bug).
This bug was introduced in version 3.0 of ibm_db. I confirmed this by testing different levels of ibm_db (all with version 11.5.8 of the ODBC driver). Version 2.8.1 and 2.8.2 ran under load for 24 hours each with no crashes. Versions 3.0 and 3.2.1 crashed approx every 30 minutes under load with various messages:
The issue is in the GetBufferParam() function introduced in version 3.0. In it, it grabs the pointer from the incoming buffer, and saves it into param:
Later, in GetOutputParameter(), after the query completes, it this code:
if(sqlTypeBinary || prm.c_type == SQL_C_BINARY) {
//str = Nan::NewOneByteString((uint8_t *) prm.buffer, prm.length).ToLocalChecked();
//prm.buffer will be freed by Garbage collector, no need to free here.
return scope.Escape(Nan::NewBuffer((char *)prm.buffer, prm.length).ToLocalChecked());
}
The issue is that NewBuffer() is taking ownership of the prm.buffer pointer to free that memory, but that was set from the incoming buffer, which ibm_db doesn't own, and will be freed by the GC.
The fix is to change the code in GetBufferParam() to malloc() and make a copy of the incoming Buffer:
This leaves the original Buffer alone, and lets the GC take care of freeing it whenever it wants to, and providing Nan::NewBuffer() a pointer that it can free whenever it wants to.
System: Linux x86_64 (Bullseye), node v18.16.1
We have a simple stored procedure call to DB2, where one of the parameters is a BINARY output parameter. We have tried both leaving the Data as the default string type and setting it to a Buffer; in both cases, node crashes due to a double memory free. This bug report is for the case of using a Buffer type. I opened #943 for non-Buffer types (since it's a different bug).
This bug was introduced in version 3.0 of ibm_db. I confirmed this by testing different levels of ibm_db (all with version 11.5.8 of the ODBC driver). Version 2.8.1 and 2.8.2 ran under load for 24 hours each with no crashes. Versions 3.0 and 3.2.1 crashed approx every 30 minutes under load with various messages:
This is the DB2 query:
The parameters are:
The call to ibm_db looks like:
The issue is in the GetBufferParam() function introduced in version 3.0. In it, it grabs the pointer from the incoming buffer, and saves it into param:
Later, in GetOutputParameter(), after the query completes, it this code:
The issue is that NewBuffer() is taking ownership of the prm.buffer pointer to free that memory, but that was set from the incoming buffer, which ibm_db doesn't own, and will be freed by the GC.
The fix is to change the code in GetBufferParam() to malloc() and make a copy of the incoming Buffer:
This leaves the original Buffer alone, and lets the GC take care of freeing it whenever it wants to, and providing Nan::NewBuffer() a pointer that it can free whenever it wants to.
PR submitted with the fix.