Skip to content

Commit

Permalink
dbfopen: fix possible memory leaks when using realloc
Browse files Browse the repository at this point in the history
Fixes OSGeo#165

Signed-off-by: Mohan Yelugoti <[email protected]>
  • Loading branch information
ymdatta committed Oct 29, 2024
1 parent 4ae3a7b commit d35f967
Showing 1 changed file with 193 additions and 16 deletions.
209 changes: 193 additions & 16 deletions dbfopen.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,24 @@ CPL_INLINE static void CPL_IGNORE_RET_VAL_INT(CPL_UNUSED int unused)
#define CPL_IGNORE_RET_VAL_INT(x) x
#endif

/************************************************************************/
/* DBFHandleFree() */
/* */
/* This is called to free out various pointers inside */
/* DBFHandle structure. */
/************************************************************************/
static void DBFHandleFree(DBFHandle psDBF)
{
free(psDBF->panFieldOffset);
free(psDBF->panFieldSize);
free(psDBF->panFieldDecimals);
free(psDBF->pachFieldType);
free(psDBF->pszHeader);
free(psDBF->pszCurrentRecord);
free(psDBF->pszWorkField);
free(psDBF->pszCodePage);
}

/************************************************************************/
/* DBFWriteHeader() */
/* */
Expand Down Expand Up @@ -459,9 +477,22 @@ DBFHandle SHPAPI_CALL DBFOpenLL(const char *pszFilename, const char *pszAccess,
/* -------------------------------------------------------------------- */
/* Read in Field Definitions */
/* -------------------------------------------------------------------- */
pabyBuf = STATIC_CAST(unsigned char *, realloc(pabyBuf, nHeadLen));
psDBF->pszHeader = REINTERPRET_CAST(char *, pabyBuf);
unsigned char *pabyBuf_realloc_ptr = STATIC_CAST(unsigned char *, realloc(pabyBuf, nHeadLen));
if (!pabyBuf_realloc_ptr)
{
psDBF->sHooks.FClose(psDBF->fp);
free(pabyBuf);
free(psDBF->pszCurrentRecord);
free(psDBF->pszCodePage);
free(psDBF);
return SHPLIB_NULLPTR;
}
else
{
pabyBuf = pabyBuf_realloc_ptr;
}

psDBF->pszHeader = REINTERPRET_CAST(char *, pabyBuf);
psDBF->sHooks.FSeek(psDBF->fp, XBASE_FILEHDR_SZ, 0);
if (psDBF->sHooks.FRead(pabyBuf, nHeadLen - XBASE_FILEHDR_SZ, 1,
psDBF->fp) != 1)
Expand Down Expand Up @@ -799,25 +830,67 @@ int SHPAPI_CALL DBFAddNativeFieldType(DBFHandle psDBF, const char *pszFieldName,

const int nOldRecordLength = psDBF->nRecordLength;
const int nOldHeaderLength = psDBF->nHeaderLength;
int *psDBF_realloc_ptr = NULL;
char *psDBF_char_realloc_ptr = NULL;

/* -------------------------------------------------------------------- */
/* realloc all the arrays larger to hold the additional field */
/* information. */
/* -------------------------------------------------------------------- */
psDBF->nFields++;

psDBF->panFieldOffset = STATIC_CAST(
psDBF_realloc_ptr = STATIC_CAST(
int *, realloc(psDBF->panFieldOffset, sizeof(int) * psDBF->nFields));

psDBF->panFieldSize = STATIC_CAST(
if (!psDBF_realloc_ptr)
{
DBFHandleFree(psDBF);
return -1;
}
else
{
psDBF->panFieldOffset = psDBF_realloc_ptr;
}

psDBF_realloc_ptr = STATIC_CAST(
int *, realloc(psDBF->panFieldSize, sizeof(int) * psDBF->nFields));

psDBF->panFieldDecimals = STATIC_CAST(
if (!psDBF_realloc_ptr)
{
DBFHandleFree(psDBF);
return -1;
}
else
{
psDBF->panFieldSize = psDBF_realloc_ptr;
}

psDBF_realloc_ptr = STATIC_CAST(
int *, realloc(psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields));

psDBF->pachFieldType = STATIC_CAST(
if (!psDBF_realloc_ptr)
{
DBFHandleFree(psDBF);
return -1;
}
else
{
psDBF->panFieldDecimals = psDBF_realloc_ptr;
}

psDBF_char_realloc_ptr = STATIC_CAST(
char *, realloc(psDBF->pachFieldType, sizeof(char) * psDBF->nFields));

if (!psDBF_char_realloc_ptr)
{
DBFHandleFree(psDBF);
return -1;
}
else
{
psDBF->pachFieldType = psDBF_char_realloc_ptr;
}

/* -------------------------------------------------------------------- */
/* Assign the new field information fields. */
/* -------------------------------------------------------------------- */
Expand All @@ -833,9 +906,19 @@ int SHPAPI_CALL DBFAddNativeFieldType(DBFHandle psDBF, const char *pszFieldName,
psDBF->nHeaderLength += XBASE_FLDHDR_SZ;
psDBF->bUpdated = FALSE;

psDBF->pszHeader = STATIC_CAST(
psDBF_char_realloc_ptr = STATIC_CAST(
char *, realloc(psDBF->pszHeader, psDBF->nFields * XBASE_FLDHDR_SZ));

if (!psDBF_char_realloc_ptr)
{
DBFHandleFree(psDBF);
return -1;
}
else
{
psDBF->pszHeader = psDBF_char_realloc_ptr;
}

char *pszFInfo = psDBF->pszHeader + XBASE_FLDHDR_SZ * (psDBF->nFields - 1);

for (int i = 0; i < XBASE_FLDHDR_SZ; i++)
Expand All @@ -859,9 +942,19 @@ int SHPAPI_CALL DBFAddNativeFieldType(DBFHandle psDBF, const char *pszFieldName,
/* -------------------------------------------------------------------- */
/* Make the current record buffer appropriately larger. */
/* -------------------------------------------------------------------- */
psDBF->pszCurrentRecord = STATIC_CAST(
psDBF_char_realloc_ptr = STATIC_CAST(
char *, realloc(psDBF->pszCurrentRecord, psDBF->nRecordLength));

if (!psDBF_char_realloc_ptr)
{
DBFHandleFree(psDBF);
return -1;
}
else
{
psDBF->pszCurrentRecord = psDBF_char_realloc_ptr;
}

/* we're done if dealing with new .dbf */
if (psDBF->bNoHeader)
return (psDBF->nFields - 1);
Expand Down Expand Up @@ -964,8 +1057,20 @@ static void *DBFReadAttribute(DBFHandle psDBF, int hEntity, int iField,
psDBF->pszWorkField =
STATIC_CAST(char *, malloc(psDBF->nWorkFieldLength));
else
psDBF->pszWorkField = STATIC_CAST(
{
char *psDBF_char_realloc_ptr = STATIC_CAST(
char *, realloc(psDBF->pszWorkField, psDBF->nWorkFieldLength));

if (!psDBF_char_realloc_ptr)
{
free(psDBF->pszWorkField);
return SHPLIB_NULLPTR;
}
else
{
psDBF->pszWorkField = psDBF_char_realloc_ptr;
}
}
}

/* -------------------------------------------------------------------- */
Expand Down Expand Up @@ -1828,6 +1933,8 @@ int SHPAPI_CALL DBFDeleteField(DBFHandle psDBF, int iField)
int nOldHeaderLength = psDBF->nHeaderLength;
int nDeletedFieldOffset = psDBF->panFieldOffset[iField];
int nDeletedFieldSize = psDBF->panFieldSize[iField];
int *psDBF_realloc_ptr = NULL;
char *psDBF_char_realloc_ptr = NULL;

/* update fields info */
for (int i = iField + 1; i < psDBF->nFields; i++)
Expand All @@ -1842,18 +1949,58 @@ int SHPAPI_CALL DBFDeleteField(DBFHandle psDBF, int iField)
/* resize fields arrays */
psDBF->nFields--;

psDBF->panFieldOffset = STATIC_CAST(
psDBF_realloc_ptr = STATIC_CAST(
int *, realloc(psDBF->panFieldOffset, sizeof(int) * psDBF->nFields));

psDBF->panFieldSize = STATIC_CAST(
if (!psDBF_realloc_ptr)
{
DBFHandleFree(psDBF);
return FALSE;
}
else
{
psDBF->panFieldOffset = psDBF_realloc_ptr;
}

psDBF_realloc_ptr = STATIC_CAST(
int *, realloc(psDBF->panFieldSize, sizeof(int) * psDBF->nFields));

psDBF->panFieldDecimals = STATIC_CAST(
if (!psDBF_realloc_ptr)
{
DBFHandleFree(psDBF);
return FALSE;
}
else
{
psDBF->panFieldSize = psDBF_realloc_ptr;
}

psDBF_realloc_ptr = STATIC_CAST(
int *, realloc(psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields));

psDBF->pachFieldType = STATIC_CAST(
if (!psDBF_realloc_ptr)
{
DBFHandleFree(psDBF);
return FALSE;
}
else
{
psDBF->panFieldDecimals = psDBF_realloc_ptr;
}

psDBF_char_realloc_ptr = STATIC_CAST(
char *, realloc(psDBF->pachFieldType, sizeof(char) * psDBF->nFields));

if (!psDBF_char_realloc_ptr)
{
DBFHandleFree(psDBF);
return FALSE;
}
else
{
psDBF->pachFieldType = psDBF_char_realloc_ptr;
}

/* update header information */
psDBF->nHeaderLength -= XBASE_FLDHDR_SZ;
psDBF->nRecordLength -= nDeletedFieldSize;
Expand All @@ -1863,13 +2010,33 @@ int SHPAPI_CALL DBFDeleteField(DBFHandle psDBF, int iField)
psDBF->pszHeader + (iField + 1) * XBASE_FLDHDR_SZ,
sizeof(char) * (psDBF->nFields - iField) * XBASE_FLDHDR_SZ);

psDBF->pszHeader = STATIC_CAST(
psDBF_char_realloc_ptr = STATIC_CAST(
char *, realloc(psDBF->pszHeader, psDBF->nFields * XBASE_FLDHDR_SZ));

if (!psDBF_char_realloc_ptr)
{
DBFHandleFree(psDBF);
return FALSE;
}
else
{
psDBF->pszHeader = psDBF_char_realloc_ptr;
}

/* update size of current record appropriately */
psDBF->pszCurrentRecord = STATIC_CAST(
psDBF_char_realloc_ptr = STATIC_CAST(
char *, realloc(psDBF->pszCurrentRecord, psDBF->nRecordLength));

if (!psDBF_char_realloc_ptr)
{
DBFHandleFree(psDBF);
return FALSE;
}
else
{
psDBF->pszCurrentRecord = psDBF_char_realloc_ptr;
}

/* we're done if we're dealing with not yet created .dbf */
if (psDBF->bNoHeader && psDBF->nRecords == 0)
return TRUE;
Expand Down Expand Up @@ -2135,8 +2302,18 @@ int SHPAPI_CALL DBFAlterFieldDefn(DBFHandle psDBF, int iField,
psDBF->panFieldOffset[i] += nWidth - nOldWidth;
psDBF->nRecordLength += nWidth - nOldWidth;

psDBF->pszCurrentRecord = STATIC_CAST(
char *psDBF_realloc_ptr = STATIC_CAST(
char *, realloc(psDBF->pszCurrentRecord, psDBF->nRecordLength));

if (!psDBF_realloc_ptr)
{
free(psDBF->pszCurrentRecord);
return FALSE;
}
else
{
psDBF->pszCurrentRecord = psDBF_realloc_ptr;
}
}

/* we're done if we're dealing with not yet created .dbf */
Expand Down

0 comments on commit d35f967

Please sign in to comment.