aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAaron Puchert <aaronpuchert@alice-dsl.net>2017-10-19 14:04:35 +0200
committerThomas Knudsen <busstoptaktik@users.noreply.github.com>2017-10-19 14:04:35 +0200
commit3ef083767eaf975399243246605fddc40cc097f9 (patch)
treeb2c45357d24f2a13850bbc46fea781a583436fc0 /src
parentfe3e7fd972682e3fec6926a7cc66ededeab55701 (diff)
downloadPROJ-3ef083767eaf975399243246605fddc40cc097f9.tar.gz
PROJ-3ef083767eaf975399243246605fddc40cc097f9.zip
Prevent crashes and leaks on allocation failure (#606)
* Prevent crashes and leaks on allocation failure Memory allocation can fail. We need to gracefully handle this case and prevent dereferencing null pointers. * Make NULL checks consistent within a file * Properly report allocation errors * Improve cleanup in pj_gc_reader.c * Implement pj_strdup and use instead of strdup The function strdup is not part of ANSI C 89, but a POSIX extension. Therefore we can not rely on it being available on all platforms.
Diffstat (limited to 'src')
-rw-r--r--src/PJ_bonne.c2
-rw-r--r--src/PJ_healpix.c4
-rw-r--r--src/PJ_laea.c2
-rw-r--r--src/bch2bps.c20
-rw-r--r--src/geod_set.c4
-rw-r--r--src/mk_cheby.c34
-rw-r--r--src/pj_datum_set.c7
-rw-r--r--src/pj_fileapi.c8
-rw-r--r--src/pj_gc_reader.c31
-rw-r--r--src/pj_gridinfo.c8
-rw-r--r--src/pj_init.c6
-rw-r--r--src/pj_malloc.c10
-rw-r--r--src/pj_pr_list.c14
-rw-r--r--src/pj_strtod.c4
-rw-r--r--src/proj_api.h1
-rw-r--r--src/projects.h1
16 files changed, 125 insertions, 31 deletions
diff --git a/src/PJ_bonne.c b/src/PJ_bonne.c
index 368829c5..711e234f 100644
--- a/src/PJ_bonne.c
+++ b/src/PJ_bonne.c
@@ -111,6 +111,8 @@ PJ *PROJECTION(bonne) {
if (P->es != 0.0) {
Q->en = pj_enfn(P->es);
+ if (0==Q->en)
+ return destructor(P, ENOMEM);
Q->m1 = pj_mlfn(Q->phi1, Q->am1 = sin(Q->phi1),
c = cos(Q->phi1), Q->en);
Q->am1 = c / (sqrt(1. - P->es * Q->am1 * Q->am1) * Q->am1);
diff --git a/src/PJ_healpix.c b/src/PJ_healpix.c
index 241d7ef4..438cb595 100644
--- a/src/PJ_healpix.c
+++ b/src/PJ_healpix.c
@@ -620,6 +620,8 @@ PJ *PROJECTION(healpix) {
if (P->es != 0.0) {
Q->apa = pj_authset(P->es); /* For auth_lat(). */
+ if (0==Q->apa)
+ return destructor(P, ENOMEM);
Q->qp = pj_qsfn(1.0, P->e, P->one_es); /* For auth_lat(). */
P->a = P->a*sqrt(0.5*Q->qp); /* Set P->a to authalic radius. */
P->ra = 1.0/P->a;
@@ -651,6 +653,8 @@ PJ *PROJECTION(rhealpix) {
return destructor (P, PJD_ERR_AXIS);
if (P->es != 0.0) {
Q->apa = pj_authset(P->es); /* For auth_lat(). */
+ if (0==Q->apa)
+ return destructor(P, ENOMEM);
Q->qp = pj_qsfn(1.0, P->e, P->one_es); /* For auth_lat(). */
P->a = P->a*sqrt(0.5*Q->qp); /* Set P->a to authalic radius. */
P->ra = 1.0/P->a;
diff --git a/src/PJ_laea.c b/src/PJ_laea.c
index ddca63d9..270b8dc8 100644
--- a/src/PJ_laea.c
+++ b/src/PJ_laea.c
@@ -255,6 +255,8 @@ PJ *PROJECTION(laea) {
Q->qp = pj_qsfn(1., P->e, P->one_es);
Q->mmf = .5 / (1. - P->es);
Q->apa = pj_authset(P->es);
+ if (0==Q->apa)
+ return destructor(P, ENOMEM);
switch (Q->mode) {
case N_POLE:
case S_POLE:
diff --git a/src/bch2bps.c b/src/bch2bps.c
index 68a4737d..c0a357c1 100644
--- a/src/bch2bps.c
+++ b/src/bch2bps.c
@@ -30,12 +30,14 @@ dadd(projUV *a, projUV *b, double m, int n) {
a++->v -= m * b++->v;
}
}
- static void /* convert row to pover series */
+ static int /* convert row to power series */
rows(projUV *c, projUV *d, int n) {
projUV sv, *dd;
int j, k;
dd = (projUV *)vector1(n-1, sizeof(projUV));
+ if (!dd)
+ return 0;
sv.u = sv.v = 0.;
for (j = 0; j < n; ++j) d[j] = dd[j] = sv;
d[0] = c[n-1];
@@ -58,14 +60,21 @@ rows(projUV *c, projUV *d, int n) {
d[0].u = -dd[0].u + .5 * c[0].u;
d[0].v = -dd[0].v + .5 * c[0].v;
pj_dalloc(dd);
+ return 1;
}
- static void /* convert columns to power series */
+ static int /* convert columns to power series */
cols(projUV **c, projUV **d, int nu, int nv) {
projUV *sv, **dd;
int j, k;
dd = (projUV **)vector2(nu, nv, sizeof(projUV));
+ if (!dd)
+ return 0;
sv = (projUV *)vector1(nv, sizeof(projUV));
+ if (!sv) {
+ freev2((void **)dd, nu);
+ return 0;
+ }
bclear(d, nu, nv);
bclear(dd, nu, nv);
bmove(d[0], c[nu-1], nv);
@@ -84,6 +93,7 @@ cols(projUV **c, projUV **d, int nu, int nv) {
submop(d[0], .5, c[0], dd[0], nv);
freev2((void **) dd, nu);
pj_dalloc(sv);
+ return 1;
}
static void /* row adjust for range -1 to 1 to a to b */
rowshft(double a, double b, projUV *d, int n) {
@@ -129,11 +139,13 @@ bch2bps(projUV a, projUV b, projUV **c, int nu, int nv) {
return 0;
/* do rows to power series */
for (i = 0; i < nu; ++i) {
- rows(c[i], d[i], nv);
+ if (!rows(c[i], d[i], nv))
+ return 0;
rowshft(a.v, b.v, d[i], nv);
}
/* do columns to power series */
- cols(d, c, nu, nv);
+ if (!cols(d, c, nu, nv))
+ return 0;
colshft(a.u, b.u, c, nu, nv);
freev2((void **) d, nu);
return 1;
diff --git a/src/geod_set.c b/src/geod_set.c
index 60f19990..16396a90 100644
--- a/src/geod_set.c
+++ b/src/geod_set.c
@@ -16,8 +16,12 @@ geod_set(int argc, char **argv) {
if (argc <= 0)
emess(1, "no arguments in initialization list");
start = curr = pj_mkparam(argv[0]);
+ if (!curr)
+ emess(1, "memory allocation failed");
for (i = 1; i < argc; ++i) {
curr->next = pj_mkparam(argv[i]);
+ if (!curr->next)
+ emess(1, "memory allocation failed");
curr = curr->next;
}
/* set elliptical parameters */
diff --git a/src/mk_cheby.c b/src/mk_cheby.c
index a7cd75c5..b074650a 100644
--- a/src/mk_cheby.c
+++ b/src/mk_cheby.c
@@ -19,18 +19,23 @@ makeT(int nru, int nrv) {
Tseries *T;
int i;
- if ((T = (Tseries *)pj_malloc(sizeof(Tseries))) &&
- (T->cu = (struct PW_COEF *)pj_malloc(
- sizeof(struct PW_COEF) * nru)) &&
- (T->cv = (struct PW_COEF *)pj_malloc(
- sizeof(struct PW_COEF) * nrv))) {
- for (i = 0; i < nru; ++i)
- T->cu[i].c = 0;
- for (i = 0; i < nrv; ++i)
- T->cv[i].c = 0;
- return T;
- } else
+ if (!(T = (Tseries *)pj_malloc(sizeof(Tseries))))
return 0;
+ if (!(T->cu = (struct PW_COEF *)pj_malloc(sizeof(struct PW_COEF) * nru))) {
+ pj_dalloc(T);
+ return 0;
+ }
+ if (!(T->cv = (struct PW_COEF *)pj_malloc(sizeof(struct PW_COEF) * nrv))) {
+ pj_dalloc(T->cu);
+ pj_dalloc(T);
+ return 0;
+ }
+
+ for (i = 0; i < nru; ++i)
+ T->cu[i].c = 0;
+ for (i = 0; i < nrv; ++i)
+ T->cv[i].c = 0;
+ return T;
}
Tseries *
mk_cheby(projUV a, projUV b, double res, projUV *resid, projUV (*func)(projUV),
@@ -40,9 +45,12 @@ mk_cheby(projUV a, projUV b, double res, projUV *resid, projUV (*func)(projUV),
projUV **w;
double cutres;
- if (!(w = (projUV **)vector2(nu, nv, sizeof(projUV))) ||
- !(ncu = (int *)vector1(nu + nv, sizeof(int))))
+ if (!(w = (projUV **)vector2(nu, nv, sizeof(projUV))))
return 0;
+ if (!(ncu = (int *)vector1(nu + nv, sizeof(int)))) {
+ freev2((void **)w, nu);
+ return 0;
+ }
ncv = ncu + nu;
if (!bchgen(a, b, nu, nv, w, func)) {
projUV *s;
diff --git a/src/pj_datum_set.c b/src/pj_datum_set.c
index 3fba68f4..c2fb1608 100644
--- a/src/pj_datum_set.c
+++ b/src/pj_datum_set.c
@@ -25,6 +25,7 @@
* DEALINGS IN THE SOFTWARE.
*****************************************************************************/
+#include <errno.h>
#include <projects.h>
#include <string.h>
@@ -101,7 +102,11 @@ int pj_datum_set(projCtx ctx, paralist *pl, PJ *projdef)
const char *date;
projdef->datum_type = PJD_GRIDSHIFT;
- projdef->catalog_name = strdup(catalog);
+ projdef->catalog_name = pj_strdup(catalog);
+ if (!projdef->catalog_name) {
+ pj_ctx_set_errno(ctx, ENOMEM);
+ return 1;
+ }
date = pj_param(ctx, pl, "sdate").s;
if( date != NULL)
diff --git a/src/pj_fileapi.c b/src/pj_fileapi.c
index 1e5bfa51..e223993e 100644
--- a/src/pj_fileapi.c
+++ b/src/pj_fileapi.c
@@ -26,6 +26,7 @@
* DEALINGS IN THE SOFTWARE.
*****************************************************************************/
+#include <errno.h>
#include <projects.h>
#include <string.h>
@@ -76,6 +77,13 @@ static PAFile pj_stdio_fopen(projCtx ctx, const char *filename,
}
pafile = (stdio_pafile *) malloc(sizeof(stdio_pafile));
+ if (!pafile)
+ {
+ pj_ctx_set_errno(ctx, ENOMEM);
+ fclose(fp);
+ return NULL;
+ }
+
pafile->fp = fp;
pafile->ctx = ctx;
return (PAFile) pafile;
diff --git a/src/pj_gc_reader.c b/src/pj_gc_reader.c
index dc528b52..e49e56a4 100644
--- a/src/pj_gc_reader.c
+++ b/src/pj_gc_reader.c
@@ -27,6 +27,7 @@
#define PJ_LIB__
+#include <errno.h>
#include <projects.h>
#include <string.h>
#include <ctype.h>
@@ -56,15 +57,29 @@ PJ_GridCatalog *pj_gc_readcatalog( projCtx ctx, const char *catalog_name )
catalog = (PJ_GridCatalog *) calloc(1,sizeof(PJ_GridCatalog));
if( !catalog )
{
+ pj_ctx_set_errno(ctx, ENOMEM);
pj_ctx_fclose(ctx, fid);
return NULL;
}
- catalog->catalog_name = strdup(catalog_name);
+ catalog->catalog_name = pj_strdup(catalog_name);
+ if (!catalog->catalog_name) {
+ pj_ctx_set_errno(ctx, ENOMEM);
+ free(catalog);
+ pj_ctx_fclose(ctx, fid);
+ return NULL;
+ }
entry_max = 10;
catalog->entries = (PJ_GridCatalogEntry *)
malloc(entry_max * sizeof(PJ_GridCatalogEntry));
+ if (!catalog->entries) {
+ pj_ctx_set_errno(ctx, ENOMEM);
+ free(catalog->catalog_name);
+ free(catalog);
+ pj_ctx_fclose(ctx, fid);
+ return NULL;
+ }
while( pj_gc_readentry( ctx, fid,
catalog->entries+catalog->entry_count) == 0)
@@ -83,6 +98,7 @@ PJ_GridCatalog *pj_gc_readcatalog( projCtx ctx, const char *catalog_name )
int i;
for( i = 0; i < catalog->entry_count; i++ )
free( catalog->entries[i].definition );
+ free( catalog->entries );
free( catalog->catalog_name );
free( catalog );
pj_ctx_fclose(ctx, fid);
@@ -124,6 +140,7 @@ static int pj_gc_read_csv_line( projCtx ctx, PAFile fid,
while( token_count < max_tokens && *next != '\0' )
{
const char *start = next;
+ char* token;
while( *next != '\0' && *next != ',' )
next++;
@@ -134,7 +151,14 @@ static int pj_gc_read_csv_line( projCtx ctx, PAFile fid,
next++;
}
- tokens[token_count++] = strdup(start);
+ token = pj_strdup(start);
+ if (!token) {
+ while (token_count > 0)
+ free(tokens[--token_count]);
+ pj_ctx_set_errno(ctx, ENOMEM);
+ return 0;
+ }
+ tokens[token_count++] = token;
}
return token_count;
@@ -199,7 +223,8 @@ static int pj_gc_readentry(projCtx ctx, PAFile fid, PJ_GridCatalogEntry *entry)
}
else
{
- entry->definition = strdup( tokens[0] );
+ entry->definition = tokens[0];
+ tokens[0] = NULL; /* We take ownership of tokens[0] */
entry->region.ll_long = dmstor_ctx( ctx, tokens[1], NULL );
entry->region.ll_lat = dmstor_ctx( ctx, tokens[2], NULL );
entry->region.ur_long = dmstor_ctx( ctx, tokens[3], NULL );
diff --git a/src/pj_gridinfo.c b/src/pj_gridinfo.c
index 458f0f2b..332a0ffb 100644
--- a/src/pj_gridinfo.c
+++ b/src/pj_gridinfo.c
@@ -570,8 +570,8 @@ static int pj_gridinfo_init_ntv2( projCtx ctx, PAFile fid, PJ_GRIDINFO *gilist )
gi = (PJ_GRIDINFO *) pj_malloc(sizeof(PJ_GRIDINFO));
memset( gi, 0, sizeof(PJ_GRIDINFO) );
- gi->gridname = strdup( gilist->gridname );
- gi->filename = strdup( gilist->filename );
+ gi->gridname = pj_strdup( gilist->gridname );
+ gi->filename = pj_strdup( gilist->filename );
gi->next = NULL;
}
@@ -866,7 +866,7 @@ PJ_GRIDINFO *pj_gridinfo_init( projCtx ctx, const char *gridname )
gilist = (PJ_GRIDINFO *) pj_malloc(sizeof(PJ_GRIDINFO));
memset( gilist, 0, sizeof(PJ_GRIDINFO) );
- gilist->gridname = strdup( gridname );
+ gilist->gridname = pj_strdup( gridname );
gilist->filename = NULL;
gilist->format = "missing";
gilist->grid_offset = 0;
@@ -882,7 +882,7 @@ PJ_GRIDINFO *pj_gridinfo_init( projCtx ctx, const char *gridname )
return gilist;
}
- gilist->filename = strdup(fname);
+ gilist->filename = pj_strdup(fname);
/* -------------------------------------------------------------------- */
/* Load a header, to determine the file type. */
diff --git a/src/pj_init.c b/src/pj_init.c
index 951f1cfb..704a8b55 100644
--- a/src/pj_init.c
+++ b/src/pj_init.c
@@ -359,6 +359,8 @@ pj_init_plus_ctx( projCtx ctx, const char *definition )
/* make a copy that we can manipulate */
defn_copy = (char *) pj_malloc( strlen(definition)+1 );
+ if (!defn_copy)
+ return NULL;
strcpy( defn_copy, definition );
/* split into arguments based on '+' and trim white space */
@@ -453,10 +455,14 @@ pj_init_ctx(projCtx ctx, int argc, char **argv) {
/* put arguments into internal linked list */
start = curr = pj_mkparam(argv[0]);
+ if (!curr)
+ return pj_dealloc_params (ctx, start, ENOMEM);
/* build parameter list and expand +init's. Does not take care of a single +init. */
for (i = 1; i < argc; ++i) {
curr->next = pj_mkparam(argv[i]);
+ if (!curr->next)
+ return pj_dealloc_params (ctx, start, ENOMEM);
/* check if +init present */
if (pj_param(ctx, curr, "tinit").i) {
diff --git a/src/pj_malloc.c b/src/pj_malloc.c
index 4e465c46..c003c717 100644
--- a/src/pj_malloc.c
+++ b/src/pj_malloc.c
@@ -130,6 +130,16 @@ pointer" to signal an error in a multi level allocation:
return 0;
}
+/**********************************************************************/
+char *pj_strdup(const char *str)
+/**********************************************************************/
+{
+ size_t len = strlen(str) + 1;
+ char *dup = pj_malloc(len);
+ if (dup)
+ memcpy(dup, str, len);
+ return dup;
+}
/*****************************************************************************/
diff --git a/src/pj_pr_list.c b/src/pj_pr_list.c
index 5ccfbe5b..00cd4bc3 100644
--- a/src/pj_pr_list.c
+++ b/src/pj_pr_list.c
@@ -62,6 +62,8 @@ char *pj_get_def( PJ *P, int options )
(void) options;
definition = (char *) pj_malloc(def_max);
+ if (!definition)
+ return NULL;
definition[0] = '\0';
for (t = P->params; t; t = t->next)
@@ -78,9 +80,15 @@ char *pj_get_def( PJ *P, int options )
def_max = def_max * 2 + l + 5;
def2 = (char *) pj_malloc(def_max);
- strcpy( def2, definition );
- pj_dalloc( definition );
- definition = def2;
+ if (def2) {
+ strcpy( def2, definition );
+ pj_dalloc( definition );
+ definition = def2;
+ }
+ else {
+ pj_dalloc( definition );
+ return NULL;
+ }
}
/* append this parameter */
diff --git a/src/pj_strtod.c b/src/pj_strtod.c
index 7c2da9a7..9a66f70f 100644
--- a/src/pj_strtod.c
+++ b/src/pj_strtod.c
@@ -102,7 +102,7 @@ static char* pj_replace_point_by_locale_point(const char* pszNumber, char point,
pszNew = pszWorkBuffer;
}
else
- pszNew = strdup(pszNumber);
+ pszNew = pj_strdup(pszNumber);
pszNew[pszPoint - pszNumber] = byPoint;
return pszNew;
}
@@ -128,7 +128,7 @@ static char* pj_replace_point_by_locale_point(const char* pszNumber, char point,
pszNew = pszWorkBuffer;
}
else
- pszNew = strdup(pszNumber);
+ pszNew = pj_strdup(pszNumber);
if( pszLocalePoint )
pszNew[pszLocalePoint - pszNumber] = ' ';
if( pszPoint )
diff --git a/src/proj_api.h b/src/proj_api.h
index 2add2946..151a824d 100644
--- a/src/proj_api.h
+++ b/src/proj_api.h
@@ -167,6 +167,7 @@ void *pj_malloc(size_t);
void pj_dalloc(void *);
void *pj_calloc (size_t n, size_t size);
void *pj_dealloc (void *ptr);
+char *pj_strdup(const char *str);
char *pj_strerrno(int);
int *pj_get_errno_ref(void);
const char *pj_get_release(void);
diff --git a/src/projects.h b/src/projects.h
index 9391835d..2af382e5 100644
--- a/src/projects.h
+++ b/src/projects.h
@@ -93,7 +93,6 @@ extern double hypot(double, double);
# include <wce_stdio.h>
# define rewind wceex_rewind
# define getenv wceex_getenv
-# define strdup _strdup
# define hypot _hypot
#endif