diff options
| author | Aaron Puchert <aaronpuchert@alice-dsl.net> | 2017-10-19 14:04:35 +0200 |
|---|---|---|
| committer | Thomas Knudsen <busstoptaktik@users.noreply.github.com> | 2017-10-19 14:04:35 +0200 |
| commit | 3ef083767eaf975399243246605fddc40cc097f9 (patch) | |
| tree | b2c45357d24f2a13850bbc46fea781a583436fc0 /src | |
| parent | fe3e7fd972682e3fec6926a7cc66ededeab55701 (diff) | |
| download | PROJ-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.c | 2 | ||||
| -rw-r--r-- | src/PJ_healpix.c | 4 | ||||
| -rw-r--r-- | src/PJ_laea.c | 2 | ||||
| -rw-r--r-- | src/bch2bps.c | 20 | ||||
| -rw-r--r-- | src/geod_set.c | 4 | ||||
| -rw-r--r-- | src/mk_cheby.c | 34 | ||||
| -rw-r--r-- | src/pj_datum_set.c | 7 | ||||
| -rw-r--r-- | src/pj_fileapi.c | 8 | ||||
| -rw-r--r-- | src/pj_gc_reader.c | 31 | ||||
| -rw-r--r-- | src/pj_gridinfo.c | 8 | ||||
| -rw-r--r-- | src/pj_init.c | 6 | ||||
| -rw-r--r-- | src/pj_malloc.c | 10 | ||||
| -rw-r--r-- | src/pj_pr_list.c | 14 | ||||
| -rw-r--r-- | src/pj_strtod.c | 4 | ||||
| -rw-r--r-- | src/proj_api.h | 1 | ||||
| -rw-r--r-- | src/projects.h | 1 |
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 |
