From ca0b01e9dfb02568f442e474c6b8059d86774851 Mon Sep 17 00:00:00 2001 From: Bborie Park Date: Fri, 21 Dec 2012 22:18:49 +0000 Subject: [PATCH] Additional cleanup and making sure to free memory when hitting errors git-svn-id: http://svn.osgeo.org/postgis/trunk@10913 b70326c6-7e19-0410-871a-916f4a2858ee --- raster/rt_core/rt_api.c | 1090 +++++++++++++++++++-------------------- 1 file changed, 537 insertions(+), 553 deletions(-) diff --git a/raster/rt_core/rt_api.c b/raster/rt_core/rt_api.c index 1a2dd0d51..6bcf40a77 100644 --- a/raster/rt_core/rt_api.c +++ b/raster/rt_core/rt_api.c @@ -1341,7 +1341,7 @@ rt_band_new_inline( /* properly set nodataval as it may need to be constrained to the data type */ if (hasnodata && rt_band_set_nodata(band, nodataval, NULL) != ES_NONE) { rterror("rt_band_new_inline: Unable to set NODATA value"); - rtdealloc(band); + rt_band_destroy(band); return NULL; } @@ -1396,26 +1396,24 @@ rt_band_new_offline( band->hasnodata = hasnodata ? 1 : 0; band->nodataval = 0; band->isnodata = FALSE; /* we don't know if the offline band is NODATA */ - band->ownsdata = 0; + band->ownsdata = 0; /* offline, flag is useless as all offline data cache is owned internally */ band->raster = NULL; /* properly set nodataval as it may need to be constrained to the data type */ if (hasnodata && rt_band_set_nodata(band, nodataval, NULL) != ES_NONE) { rterror("rt_band_new_offline: Unable to set NODATA value"); - rtdealloc(band); + rt_band_destroy(band); return NULL; } - band->ownsdata = 0; /* offline, flag is useless as all offline data cache is owned internally */ - band->data.offline.bandNum = bandNum; /* memory for data.offline.path is managed internally */ pathlen = strlen(path); band->data.offline.path = rtalloc(sizeof(char) * (pathlen + 1)); - if (band == NULL) { + if (band->data.offline.path == NULL) { rterror("rt_band_new_offline: Out of memory allocating offline path"); - rtdealloc(band); + rt_band_destroy(band); return NULL; } memcpy(band->data.offline.path, path, pathlen); @@ -1443,19 +1441,11 @@ rt_band_duplicate(rt_band band) { /* offline */ if (band->offline) { - char *path = NULL; - path = rtalloc(sizeof(char) * (strlen(band->data.offline.path) + 1)); - if (path == NULL) { - rterror("rt_band_duplicate: Out of memory allocating offline band path"); - return NULL; - } - strcpy(path, band->data.offline.path); - rtn = rt_band_new_offline( band->width, band->height, band->pixtype, band->hasnodata, band->nodataval, - band->data.offline.bandNum, (const char *) path + band->data.offline.bandNum, (const char *) band->data.offline.path ); } /* online */ @@ -1477,8 +1467,10 @@ rt_band_duplicate(rt_band band) { rt_band_set_ownsdata_flag(rtn, 1); /* we DO own this data!!! */ } - if (rtn == NULL) + if (rtn == NULL) { rterror("rt_band_duplicate: Could not copy band"); + return NULL; + } return rtn; } @@ -1498,25 +1490,26 @@ rt_band_is_offline(rt_band band) { * @param band : the band to destroy */ void -rt_band_destroy(rt_band band) { - +rt_band_destroy(rt_band band) { + if (band == NULL) + return; - RASTER_DEBUGF(3, "Destroying rt_band @ %p", band); + RASTER_DEBUGF(3, "Destroying rt_band @ %p", band); - /* offline band */ - if (band->offline) { - /* memory cache */ - if (band->data.offline.mem != NULL) - rtdealloc(band->data.offline.mem); - /* offline file path */ - if (band->data.offline.path != NULL) - rtdealloc(band->data.offline.path); - } - /* inline band and band owns the data */ - else if (band->data.mem != NULL && band->ownsdata) - rtdealloc(band->data.mem); + /* offline band */ + if (band->offline) { + /* memory cache */ + if (band->data.offline.mem != NULL) + rtdealloc(band->data.offline.mem); + /* offline file path */ + if (band->data.offline.path != NULL) + rtdealloc(band->data.offline.path); + } + /* inline band and band owns the data */ + else if (band->data.mem != NULL && band->ownsdata) + rtdealloc(band->data.mem); - rtdealloc(band); + rtdealloc(band); } const char* @@ -5166,10 +5159,9 @@ rt_raster_new(uint32_t width, uint32_t height) { RASTER_DEBUGF(3, "Created rt_raster @ %p", ret); - assert(NULL != ret); - if (width > 65535 || height > 65535) { rterror("rt_raster_new: Dimensions requested exceed the maximum (65535 x 65535) permitted for a raster"); + rt_raster_destroy(ret); return NULL; } @@ -5184,20 +5176,22 @@ rt_raster_new(uint32_t width, uint32_t height) { ret->srid = SRID_UNKNOWN; ret->numBands = 0; - ret->bands = 0; + ret->bands = NULL; + return ret; } void rt_raster_destroy(rt_raster raster) { + if (raster == NULL) + return; + RASTER_DEBUGF(3, "Destroying rt_raster @ %p", raster); - RASTER_DEBUGF(3, "Destroying rt_raster @ %p", raster); + if (raster->bands) + rtdealloc(raster->bands); - if (raster->bands) { - rtdealloc(raster->bands); - } - rtdealloc(raster); + rtdealloc(raster); } uint16_t @@ -7182,245 +7176,240 @@ write_float64(uint8_t** to, uint8_t littleEndian, double v) /* Read band from WKB as at start of band */ static rt_band -rt_band_from_wkb(uint16_t width, uint16_t height, - const uint8_t** ptr, const uint8_t* end, - uint8_t littleEndian) { - rt_band band = NULL; - int pixbytes = 0; - uint8_t type = 0; - unsigned long sz = 0; - uint32_t v = 0; +rt_band_from_wkb( + uint16_t width, uint16_t height, + const uint8_t** ptr, const uint8_t* end, + uint8_t littleEndian +) { + rt_band band = NULL; + int pixbytes = 0; + uint8_t type = 0; + unsigned long sz = 0; + uint32_t v = 0; + assert(NULL != ptr); + assert(NULL != end); + band = rtalloc(sizeof (struct rt_band_t)); + if (!band) { + rterror("rt_band_from_wkb: Out of memory allocating rt_band during WKB parsing"); + return NULL; + } + band->ownsdata = 0; /* assume we don't own data */ - assert(NULL != ptr); - assert(NULL != end); + if (end - *ptr < 1) { + rterror("rt_band_from_wkb: Premature end of WKB on band reading (%s:%d)", + __FILE__, __LINE__); + rt_band_destroy(band); + return NULL; + } + type = read_uint8(ptr); - band = rtalloc(sizeof (struct rt_band_t)); - if (!band) { - rterror("rt_band_from_wkb: Out of memory allocating rt_band during WKB parsing"); - return 0; - } + if ((type & BANDTYPE_PIXTYPE_MASK) >= PT_END) { + rterror("rt_band_from_wkb: Invalid pixtype %d", type & BANDTYPE_PIXTYPE_MASK); + rt_band_destroy(band); + return NULL; + } - if (end - *ptr < 1) { - rterror("rt_band_from_wkb: Premature end of WKB on band reading (%s:%d)", - __FILE__, __LINE__); - return 0; - } - type = read_uint8(ptr); + band->pixtype = type & BANDTYPE_PIXTYPE_MASK; + band->offline = BANDTYPE_IS_OFFDB(type) ? 1 : 0; + band->hasnodata = BANDTYPE_HAS_NODATA(type) ? 1 : 0; + band->isnodata = band->hasnodata ? (BANDTYPE_IS_NODATA(type) ? 1 : 0) : 0; + band->width = width; + band->height = height; - if ((type & BANDTYPE_PIXTYPE_MASK) >= PT_END) { - rterror("rt_band_from_wkb: Invalid pixtype %d", type & BANDTYPE_PIXTYPE_MASK); - rtdealloc(band); - return 0; - } - assert(NULL != band); + RASTER_DEBUGF(3, " Band pixtype:%s, offline:%d, hasnodata:%d", + rt_pixtype_name(band->pixtype), + band->offline, + band->hasnodata + ); - band->pixtype = type & BANDTYPE_PIXTYPE_MASK; - band->offline = BANDTYPE_IS_OFFDB(type) ? 1 : 0; - band->hasnodata = BANDTYPE_HAS_NODATA(type) ? 1 : 0; - band->isnodata = band->hasnodata ? (BANDTYPE_IS_NODATA(type) ? 1 : 0) : 0; - band->width = width; - band->height = height; + /* Check there's enough bytes to read nodata value */ + pixbytes = rt_pixtype_size(band->pixtype); + if (((*ptr) + pixbytes) >= end) { + rterror("rt_band_from_wkb: Premature end of WKB on band novalue reading"); + rt_band_destroy(band); + return NULL; + } - RASTER_DEBUGF(3, " Band pixtype:%s, offline:%d, hasnodata:%d", - rt_pixtype_name(band->pixtype), - band->offline, - band->hasnodata); + /* Read nodata value */ + switch (band->pixtype) { + case PT_1BB: { + band->nodataval = ((int) read_uint8(ptr)) & 0x01; + break; + } + case PT_2BUI: { + band->nodataval = ((int) read_uint8(ptr)) & 0x03; + break; + } + case PT_4BUI: { + band->nodataval = ((int) read_uint8(ptr)) & 0x0F; + break; + } + case PT_8BSI: { + band->nodataval = read_int8(ptr); + break; + } + case PT_8BUI: { + band->nodataval = read_uint8(ptr); + break; + } + case PT_16BSI: { + band->nodataval = read_int16(ptr, littleEndian); + break; + } + case PT_16BUI: { + band->nodataval = read_uint16(ptr, littleEndian); + break; + } + case PT_32BSI: { + band->nodataval = read_int32(ptr, littleEndian); + break; + } + case PT_32BUI: { + band->nodataval = read_uint32(ptr, littleEndian); + break; + } + case PT_32BF: { + band->nodataval = read_float32(ptr, littleEndian); + break; + } + case PT_64BF: { + band->nodataval = read_float64(ptr, littleEndian); + break; + } + default: { + rterror("rt_band_from_wkb: Unknown pixeltype %d", band->pixtype); + rt_band_destroy(band); + return NULL; + } + } - /* Check there's enough bytes to read nodata value */ + RASTER_DEBUGF(3, " Nodata value: %g, pixbytes: %d, ptr @ %p, end @ %p", + band->nodataval, pixbytes, *ptr, end); - pixbytes = rt_pixtype_size(band->pixtype); - if (((*ptr) + pixbytes) >= end) { - rterror("rt_band_from_wkb: Premature end of WKB on band novalue reading"); - rtdealloc(band); - return 0; - } + if (band->offline) { + if (((*ptr) + 1) >= end) { + rterror("rt_band_from_wkb: Premature end of WKB on offline " + "band data bandNum reading (%s:%d)", + __FILE__, __LINE__ + ); + rt_band_destroy(band); + return NULL; + } - /* Read nodata value */ - switch (band->pixtype) { - case PT_1BB: - { - band->nodataval = ((int) read_uint8(ptr)) & 0x01; - break; - } - case PT_2BUI: - { - band->nodataval = ((int) read_uint8(ptr)) & 0x03; - break; - } - case PT_4BUI: - { - band->nodataval = ((int) read_uint8(ptr)) & 0x0F; - break; - } - case PT_8BSI: - { - band->nodataval = read_int8(ptr); - break; - } - case PT_8BUI: - { - band->nodataval = read_uint8(ptr); - break; - } - case PT_16BSI: - { - band->nodataval = read_int16(ptr, littleEndian); - break; - } - case PT_16BUI: - { - band->nodataval = read_uint16(ptr, littleEndian); - break; - } - case PT_32BSI: - { - band->nodataval = read_int32(ptr, littleEndian); - break; - } - case PT_32BUI: - { - band->nodataval = read_uint32(ptr, littleEndian); - break; - } - case PT_32BF: - { - band->nodataval = read_float32(ptr, littleEndian); - break; - } - case PT_64BF: - { - band->nodataval = read_float64(ptr, littleEndian); - break; - } - default: - { - rterror("rt_band_from_wkb: Unknown pixeltype %d", band->pixtype); - rtdealloc(band); - return 0; - } - } + band->data.offline.bandNum = read_int8(ptr); + band->data.offline.mem = NULL; - RASTER_DEBUGF(3, " Nodata value: %g, pixbytes: %d, ptr @ %p, end @ %p", - band->nodataval, pixbytes, *ptr, end); + { + /* check we have a NULL-termination */ + sz = 0; + while ((*ptr)[sz] && &((*ptr)[sz]) < end) ++sz; + if (&((*ptr)[sz]) >= end) { + rterror("rt_band_from_wkb: Premature end of WKB on band offline path reading"); + rt_band_destroy(band); + return NULL; + } - if (band->offline) { - if (((*ptr) + 1) >= end) { - rterror("rt_band_from_wkb: Premature end of WKB on offline " - "band data bandNum reading (%s:%d)", - __FILE__, __LINE__); - rtdealloc(band); - return 0; - } - band->data.offline.bandNum = read_int8(ptr); + /* we never own offline band data */ + band->ownsdata = 0; - band->data.offline.mem = NULL; + band->data.offline.path = rtalloc(sz + 1); + if (band->data.offline.path == NULL) { + rterror("rt_band_from_wkb: Out of memory allocating for offline path of band"); + rt_band_destroy(band); + return NULL; + } - { - /* check we have a NULL-termination */ - sz = 0; - while ((*ptr)[sz] && &((*ptr)[sz]) < end) ++sz; - if (&((*ptr)[sz]) >= end) { - rterror("rt_band_from_wkb: Premature end of WKB on band offline path reading"); - rtdealloc(band); - return 0; - } + memcpy(band->data.offline.path, *ptr, sz); + band->data.offline.path[sz] = '\0'; - band->ownsdata = 0; + RASTER_DEBUGF(3, "OFFDB band path is %s (size is %d)", + band->data.offline.path, sz); - band->data.offline.path = rtalloc(sz + 1); - memcpy(band->data.offline.path, *ptr, sz); - band->data.offline.path[sz] = '\0'; + *ptr += sz + 1; - RASTER_DEBUGF(3, "OFFDB band path is %s (size is %d)", - band->data.offline.path, sz); + /* TODO: How could we know if the offline band is a nodata band? */ + /* trust in the force */ + /*band->isnodata = FALSE;*/ + } - *ptr += sz + 1; + return band; + } - /* TODO: How could we know if the offline band is a nodata band? */ - /* trust in the force */ - /*band->isnodata = FALSE;*/ - } - return band; - } + /* This is an on-disk band */ + sz = width * height * pixbytes; + if (((*ptr) + sz) > end) { + rterror("rt_band_from_wkb: Premature end of WKB on band data reading (%s:%d)", + __FILE__, __LINE__); + rt_band_destroy(band); + return NULL; + } - /* This is an on-disk band */ - sz = width * height * pixbytes; - if (((*ptr) + sz) > end) { - rterror("rt_band_from_wkb: Premature end of WKB on band data reading (%s:%d)", - __FILE__, __LINE__); - rtdealloc(band); - return 0; - } + band->data.mem = rtalloc(sz); + if (!band->data.mem) { + rterror("rt_band_from_wkb: Out of memory during band creation in WKB parser"); + rt_band_destroy(band); + return NULL; + } - band->data.mem = rtalloc(sz); - if (!band->data.mem) { - rterror("rt_band_from_wkb: Out of memory during band creation in WKB parser"); - rtdealloc(band); - return 0; - } + band->ownsdata = 1; /* we DO own this data!!! */ + memcpy(band->data.mem, *ptr, sz); + *ptr += sz; - band->ownsdata = 1; /* we DO own this data!!! */ - memcpy(band->data.mem, *ptr, sz); - *ptr += sz; + /* Should now flip values if > 8bit and + * littleEndian != isMachineLittleEndian */ + if (pixbytes > 1) { + if (isMachineLittleEndian() != littleEndian) { + void (*flipper)(uint8_t*) = 0; + uint8_t *flipme = NULL; - /* Should now flip values if > 8bit and - * littleEndian != isMachineLittleEndian */ - if (pixbytes > 1) { - if (isMachineLittleEndian() != littleEndian) { - { - void (*flipper)(uint8_t*) = 0; - uint8_t *flipme = NULL; - - if (pixbytes == 2) flipper = flip_endian_16; - else if (pixbytes == 4) flipper = flip_endian_32; - else if (pixbytes == 8) flipper = flip_endian_64; - else { - rterror("rt_band_from_wkb: Unexpected pix bytes %d", pixbytes); - rtdealloc(band); - rtdealloc(band->data.mem); - return 0; - } - - flipme = band->data.mem; - sz = width * height; - for (v = 0; v < sz; ++v) { - flipper(flipme); - flipme += pixbytes; - } - } - } - } - /* And should check for invalid values for < 8bit types */ - else if (band->pixtype == PT_1BB || - band->pixtype == PT_2BUI || - band->pixtype == PT_4BUI) { - { - uint8_t maxVal = band->pixtype == PT_1BB ? 1 : - band->pixtype == PT_2BUI ? 3 : - 15; - uint8_t val; - - sz = width*height; - for (v = 0; v < sz; ++v) { - val = ((uint8_t*) band->data.mem)[v]; - if (val > maxVal) { - rterror("rt_band_from_wkb: Invalid value %d for pixel of type %s", - val, rt_pixtype_name(band->pixtype)); - rtdealloc(band->data.mem); - rtdealloc(band); - return 0; - } - } - } - } + if (pixbytes == 2) + flipper = flip_endian_16; + else if (pixbytes == 4) + flipper = flip_endian_32; + else if (pixbytes == 8) + flipper = flip_endian_64; + else { + rterror("rt_band_from_wkb: Unexpected pix bytes %d", pixbytes); + rt_band_destroy(band); + return NULL; + } + + flipme = band->data.mem; + sz = width * height; + for (v = 0; v < sz; ++v) { + flipper(flipme); + flipme += pixbytes; + } + } + } + /* And should check for invalid values for < 8bit types */ + else if ( + band->pixtype == PT_1BB || + band->pixtype == PT_2BUI || + band->pixtype == PT_4BUI + ) { + uint8_t maxVal = band->pixtype == PT_1BB ? 1 : (band->pixtype == PT_2BUI ? 3 : 15); + uint8_t val; + + sz = width*height; + for (v = 0; v < sz; ++v) { + val = ((uint8_t*) band->data.mem)[v]; + if (val > maxVal) { + rterror("rt_band_from_wkb: Invalid value %d for pixel of type %s", + val, rt_pixtype_name(band->pixtype)); + rt_band_destroy(band); + return NULL; + } + } + } - /* And we should check if the band is a nodata band */ - /* TODO: No!! This is too slow */ - /*rt_band_check_is_nodata(band);*/ + /* And we should check if the band is a nodata band */ + /* TODO: No!! This is too slow */ + /*rt_band_check_is_nodata(band);*/ - return band; + return band; } /* -4 for size, +1 for endian */ @@ -7428,167 +7417,166 @@ rt_band_from_wkb(uint16_t width, uint16_t height, rt_raster rt_raster_from_wkb(const uint8_t* wkb, uint32_t wkbsize) { - const uint8_t *ptr = wkb; - const uint8_t *wkbend = NULL; - rt_raster rast = NULL; - uint8_t endian = 0; - uint16_t version = 0; - uint16_t i = 0; - - + const uint8_t *ptr = wkb; + const uint8_t *wkbend = NULL; + rt_raster rast = NULL; + uint8_t endian = 0; + uint16_t version = 0; + uint16_t i = 0; + uint16_t j = 0; - assert(NULL != ptr); + assert(NULL != ptr); - /* Check that wkbsize is >= sizeof(rt_raster_serialized) */ - if (wkbsize < RT_WKB_HDR_SZ) { - rterror("rt_raster_from_wkb: wkb size (%d) < min size (%d)", - wkbsize, RT_WKB_HDR_SZ); - return 0; - } - wkbend = wkb + wkbsize; + /* Check that wkbsize is >= sizeof(rt_raster_serialized) */ + if (wkbsize < RT_WKB_HDR_SZ) { + rterror("rt_raster_from_wkb: wkb size (%d) < min size (%d)", + wkbsize, RT_WKB_HDR_SZ); + return NULL; + } + wkbend = wkb + wkbsize; - RASTER_DEBUGF(3, "Parsing header from wkb position %d (expected 0)", - d_binptr_to_pos(ptr, wkbend, wkbsize)); + RASTER_DEBUGF(3, "Parsing header from wkb position %d (expected 0)", + d_binptr_to_pos(ptr, wkbend, wkbsize)); + CHECK_BINPTR_POSITION(ptr, wkbend, wkbsize, 0); - CHECK_BINPTR_POSITION(ptr, wkbend, wkbsize, 0); + /* Read endianness */ + endian = *ptr; + ptr += 1; - /* Read endianness */ - endian = *ptr; - ptr += 1; + /* Read version of protocol */ + version = read_uint16(&ptr, endian); + if (version != 0) { + rterror("rt_raster_from_wkb: WKB version %d unsupported", version); + return NULL; + } - /* Read version of protocol */ - version = read_uint16(&ptr, endian); - if (version != 0) { - rterror("rt_raster_from_wkb: WKB version %d unsupported", version); - return 0; - } + /* Read other components of raster header */ + rast = (rt_raster) rtalloc(sizeof (struct rt_raster_t)); + if (!rast) { + rterror("rt_raster_from_wkb: Out of memory allocating raster for wkb input"); + return NULL; + } - /* Read other components of raster header */ - rast = (rt_raster) rtalloc(sizeof (struct rt_raster_t)); - if (!rast) { - rterror("rt_raster_from_wkb: Out of memory allocating raster for wkb input"); - return 0; - } - rast->numBands = read_uint16(&ptr, endian); - rast->scaleX = read_float64(&ptr, endian); - rast->scaleY = read_float64(&ptr, endian); - rast->ipX = read_float64(&ptr, endian); - rast->ipY = read_float64(&ptr, endian); - rast->skewX = read_float64(&ptr, endian); - rast->skewY = read_float64(&ptr, endian); - rt_raster_set_srid(rast, read_int32(&ptr, endian)); - rast->width = read_uint16(&ptr, endian); - rast->height = read_uint16(&ptr, endian); - - /* Consistency checking, should have been checked before */ - assert(ptr <= wkbend); - - RASTER_DEBUGF(3, "rt_raster_from_wkb: Raster numBands: %d", - rast->numBands); - RASTER_DEBUGF(3, "rt_raster_from_wkb: Raster scale: %gx%g", - rast->scaleX, rast->scaleY); - RASTER_DEBUGF(3, "rt_raster_from_wkb: Raster ip: %gx%g", - rast->ipX, rast->ipY); - RASTER_DEBUGF(3, "rt_raster_from_wkb: Raster skew: %gx%g", - rast->skewX, rast->skewY); - RASTER_DEBUGF(3, "rt_raster_from_wkb: Raster srid: %d", - rast->srid); - RASTER_DEBUGF(3, "rt_raster_from_wkb: Raster dims: %dx%d", - rast->width, rast->height); - RASTER_DEBUGF(3, "Parsing raster header finished at wkb position %d (expected 61)", - d_binptr_to_pos(ptr, wkbend, wkbsize)); - - CHECK_BINPTR_POSITION(ptr, wkbend, wkbsize, 61); - - /* Read all bands of raster */ - - if (!rast->numBands) { - /* Here ptr should have been left to right after last used byte */ - if (ptr < wkbend) { - rtwarn("%d bytes of WKB remained unparsed", wkbend - ptr); - } else if (ptr > wkbend) { - /* Easier to get a segfault before I guess */ - rtwarn("We parsed %d bytes more then available!", ptr - wkbend); - } - rast->bands = 0; - return rast; - } + rast->numBands = read_uint16(&ptr, endian); + rast->scaleX = read_float64(&ptr, endian); + rast->scaleY = read_float64(&ptr, endian); + rast->ipX = read_float64(&ptr, endian); + rast->ipY = read_float64(&ptr, endian); + rast->skewX = read_float64(&ptr, endian); + rast->skewY = read_float64(&ptr, endian); + rt_raster_set_srid(rast, read_int32(&ptr, endian)); + rast->width = read_uint16(&ptr, endian); + rast->height = read_uint16(&ptr, endian); + + /* Consistency checking, should have been checked before */ + assert(ptr <= wkbend); + + RASTER_DEBUGF(3, "rt_raster_from_wkb: Raster numBands: %d", + rast->numBands); + RASTER_DEBUGF(3, "rt_raster_from_wkb: Raster scale: %gx%g", + rast->scaleX, rast->scaleY); + RASTER_DEBUGF(3, "rt_raster_from_wkb: Raster ip: %gx%g", + rast->ipX, rast->ipY); + RASTER_DEBUGF(3, "rt_raster_from_wkb: Raster skew: %gx%g", + rast->skewX, rast->skewY); + RASTER_DEBUGF(3, "rt_raster_from_wkb: Raster srid: %d", + rast->srid); + RASTER_DEBUGF(3, "rt_raster_from_wkb: Raster dims: %dx%d", + rast->width, rast->height); + RASTER_DEBUGF(3, "Parsing raster header finished at wkb position %d (expected 61)", + d_binptr_to_pos(ptr, wkbend, wkbsize)); + + CHECK_BINPTR_POSITION(ptr, wkbend, wkbsize, 61); + + /* Read all bands of raster */ + if (!rast->numBands) { + /* Here ptr should have been left to right after last used byte */ + if (ptr < wkbend) { + rtwarn("%d bytes of WKB remained unparsed", wkbend - ptr); + } + else if (ptr > wkbend) { + /* Easier to get a segfault before I guess */ + rtwarn("We parsed %d bytes more then available!", ptr - wkbend); + } + + rast->bands = NULL; + return rast; + } + + /* Now read the bands */ + rast->bands = (rt_band*) rtalloc(sizeof(rt_band) * rast->numBands); + if (!rast->bands) { + rterror("rt_raster_from_wkb: Out of memory allocating bands for WKB raster decoding"); + rt_raster_destroy(rast); + return NULL; + } - /* Now read the bands */ - rast->bands = (rt_band*) rtalloc(sizeof (rt_band) * rast->numBands); - if (!rast->bands) { - rterror("rt_raster_from_wkb: Out of memory allocating bands for WKB raster decoding"); - rtdealloc(rast); - return 0; - } + /* ptr should now point to start of first band */ + /* we should have checked this before */ + assert(ptr <= wkbend); - /* ptr should now point to start of first band */ - assert(ptr <= wkbend); /* we should have checked this before */ + for (i = 0; i < rast->numBands; ++i) { + RASTER_DEBUGF(3, "Parsing band %d from wkb position %d", i, + d_binptr_to_pos(ptr, wkbend, wkbsize)); - for (i = 0; i < rast->numBands; ++i) { - RASTER_DEBUGF(3, "Parsing band %d from wkb position %d", i, - d_binptr_to_pos(ptr, wkbend, wkbsize)); + rt_band band = rt_band_from_wkb(rast->width, rast->height, + &ptr, wkbend, endian); + if (!band) { + rterror("rt_raster_from_wkb: Error reading WKB form of band %d", i); + for (j = 0; j < i; j++) rt_band_destroy(rast->bands[j]); + rt_raster_destroy(rast); + return NULL; + } - rt_band band = rt_band_from_wkb(rast->width, rast->height, - &ptr, wkbend, endian); - if (!band) { - rterror("rt_raster_from_wkb: Error reading WKB form of band %d", i); - rtdealloc(rast); - /* TODO: dealloc any previously allocated band too ! */ - return 0; - } - band->raster = rast; - rast->bands[i] = band; - } + band->raster = rast; + rast->bands[i] = band; + } - /* Here ptr should have been left to right after last used byte */ - if (ptr < wkbend) { - rtwarn("%d bytes of WKB remained unparsed", wkbend - ptr); - } else if (ptr > wkbend) { - /* Easier to get a segfault before I guess */ - rtwarn("We parsed %d bytes more then available!", - ptr - wkbend); - } + /* Here ptr should have been left to right after last used byte */ + if (ptr < wkbend) { + rtwarn("%d bytes of WKB remained unparsed", wkbend - ptr); + } + else if (ptr > wkbend) { + /* Easier to get a segfault before I guess */ + rtwarn("We parsed %d bytes more then available!", ptr - wkbend); + } - assert(NULL != rast); - return rast; + return rast; } rt_raster -rt_raster_from_hexwkb(const char* hexwkb, - uint32_t hexwkbsize) { - uint8_t* wkb = NULL; - uint32_t wkbsize = 0; - uint32_t i = 0; - - - - assert(NULL != hexwkb); +rt_raster_from_hexwkb(const char* hexwkb, uint32_t hexwkbsize) { + rt_raster ret = NULL; + uint8_t* wkb = NULL; + uint32_t wkbsize = 0; + uint32_t i = 0; - RASTER_DEBUGF(3, "rt_raster_from_hexwkb: input wkb: %s", hexwkb); + assert(NULL != hexwkb); - if (hexwkbsize % 2) { - rterror("rt_raster_from_hexwkb: Raster HEXWKB input must have an even number of characters"); - return 0; - } - wkbsize = hexwkbsize / 2; + RASTER_DEBUGF(3, "rt_raster_from_hexwkb: input wkb: %s", hexwkb); - wkb = rtalloc(wkbsize); - if (!wkb) { - rterror("rt_raster_from_hexwkb: Out of memory allocating memory for decoding HEXWKB"); - return 0; - } + if (hexwkbsize % 2) { + rterror("rt_raster_from_hexwkb: Raster HEXWKB input must have an even number of characters"); + return NULL; + } + wkbsize = hexwkbsize / 2; - for (i = 0; i < wkbsize; ++i) /* parse full hex */ { - wkb[i] = parse_hex((char*) & (hexwkb[i * 2])); - } + wkb = rtalloc(wkbsize); + if (!wkb) { + rterror("rt_raster_from_hexwkb: Out of memory allocating memory for decoding HEXWKB"); + return NULL; + } - rt_raster ret = rt_raster_from_wkb(wkb, wkbsize); + /* parse full hex */ + for (i = 0; i < wkbsize; ++i) { + wkb[i] = parse_hex((char*) & (hexwkb[i * 2])); + } - rtdealloc(wkb); /* as long as rt_raster_from_wkb copies memory */ + ret = rt_raster_from_wkb(wkb, wkbsize); + rtdealloc(wkb); /* as long as rt_raster_from_wkb copies memory */ - return ret; + return ret; } static uint32_t @@ -8107,199 +8095,195 @@ rt_raster_serialize(rt_raster raster) { */ rt_raster rt_raster_deserialize(void* serialized, int header_only) { - rt_raster rast = NULL; - const uint8_t *ptr = NULL; - const uint8_t *beg = NULL; - uint16_t i = 0; - uint8_t littleEndian = isMachineLittleEndian(); - + rt_raster rast = NULL; + const uint8_t *ptr = NULL; + const uint8_t *beg = NULL; + uint16_t i = 0; + uint16_t j = 0; + uint8_t littleEndian = isMachineLittleEndian(); + assert(NULL != serialized); - assert(NULL != serialized); + RASTER_DEBUG(2, "rt_raster_deserialize: Entering..."); - RASTER_DEBUG(2, "rt_raster_deserialize: Entering..."); + /* NOTE: Value of rt_raster.size may be different + * than actual size of raster data being read. + * See note on SET_VARSIZE in rt_raster_serialize function above. + */ - /* NOTE: Value of rt_raster.size may be different - * than actual size of raster data being read. - * See note on SET_VARSIZE in rt_raster_serialize function above. - */ + /* Allocate memory for deserialized raster header */ + RASTER_DEBUG(3, "rt_raster_deserialize: Allocating memory for deserialized raster header"); + rast = (rt_raster) rtalloc(sizeof (struct rt_raster_t)); + if (!rast) { + rterror("rt_raster_deserialize: Out of memory allocating raster for deserialization"); + return NULL; + } - /* Allocate memory for deserialized raster header */ + /* Deserialize raster header */ + RASTER_DEBUG(3, "rt_raster_deserialize: Deserialize raster header"); + memcpy(rast, serialized, sizeof (struct rt_raster_serialized_t)); - RASTER_DEBUG(3, "rt_raster_deserialize: Allocating memory for deserialized raster header"); - rast = (rt_raster) rtalloc(sizeof (struct rt_raster_t)); - if (!rast) { - rterror("rt_raster_deserialize: Out of memory allocating raster for deserialization"); - return 0; - } + if (0 == rast->numBands || header_only) { + rast->bands = 0; + return rast; + } - /* Deserialize raster header */ - RASTER_DEBUG(3, "rt_raster_deserialize: Deserialize raster header"); - memcpy(rast, serialized, sizeof (struct rt_raster_serialized_t)); + beg = (const uint8_t*) serialized; - if (0 == rast->numBands || header_only) { - rast->bands = 0; - return rast; - } - beg = (const uint8_t*) serialized; + /* Allocate registry of raster bands */ + RASTER_DEBUG(3, "rt_raster_deserialize: Allocating memory for bands"); + rast->bands = rtalloc(rast->numBands * sizeof (rt_band)); + if (rast->bands == NULL) { + rterror("rt_raster_deserialize: Out of memory allocating bands"); + rtdealloc(rast); + return NULL; + } - RASTER_DEBUG(3, "rt_raster_deserialize: Allocating memory for bands"); - /* Allocate registry of raster bands */ - rast->bands = rtalloc(rast->numBands * sizeof (rt_band)); + RASTER_DEBUGF(3, "rt_raster_deserialize: %d bands", rast->numBands); - RASTER_DEBUGF(3, "rt_raster_deserialize: %d bands", rast->numBands); + /* Move to the beginning of first band */ + ptr = beg; + ptr += sizeof (struct rt_raster_serialized_t); - /* Move to the beginning of first band */ - ptr = beg; - ptr += sizeof (struct rt_raster_serialized_t); + /* Deserialize bands now */ + for (i = 0; i < rast->numBands; ++i) { + rt_band band = NULL; + uint8_t type = 0; + int pixbytes = 0; - /* Deserialize bands now */ - for (i = 0; i < rast->numBands; ++i) { - rt_band band = NULL; - uint8_t type = 0; - int pixbytes = 0; + band = rtalloc(sizeof(struct rt_band_t)); + if (!band) { + rterror("rt_raster_deserialize: Out of memory allocating rt_band during deserialization"); + for (j = 0; j < i; j++) rt_band_destroy(rast->bands[j]); + rt_raster_destroy(rast); + return NULL; + } - band = rtalloc(sizeof (struct rt_band_t)); - if (!band) { - rterror("rt_raster_deserialize: Out of memory allocating rt_band during deserialization"); - return 0; - } + rast->bands[i] = band; - rast->bands[i] = band; + type = *ptr; + ptr++; + band->pixtype = type & BANDTYPE_PIXTYPE_MASK; - type = *ptr; - ptr++; - band->pixtype = type & BANDTYPE_PIXTYPE_MASK; + RASTER_DEBUGF(3, "rt_raster_deserialize: band %d with pixel type %s", i, rt_pixtype_name(band->pixtype)); - RASTER_DEBUGF(3, "rt_raster_deserialize: band %d with pixel type %s", i, rt_pixtype_name(band->pixtype)); + band->offline = BANDTYPE_IS_OFFDB(type) ? 1 : 0; + band->hasnodata = BANDTYPE_HAS_NODATA(type) ? 1 : 0; + band->isnodata = band->hasnodata ? (BANDTYPE_IS_NODATA(type) ? 1 : 0) : 0; + band->width = rast->width; + band->height = rast->height; + band->ownsdata = 0; /* we do NOT own this data!!! */ + band->raster = rast; - band->offline = BANDTYPE_IS_OFFDB(type) ? 1 : 0; - band->hasnodata = BANDTYPE_HAS_NODATA(type) ? 1 : 0; - band->isnodata = band->hasnodata ? (BANDTYPE_IS_NODATA(type) ? 1 : 0) : 0; - band->width = rast->width; - band->height = rast->height; - band->ownsdata = 0; /* we do NOT own this data!!! */ - band->raster = rast; + /* Advance by data padding */ + pixbytes = rt_pixtype_size(band->pixtype); + ptr += pixbytes - 1; - /* Advance by data padding */ - pixbytes = rt_pixtype_size(band->pixtype); - ptr += pixbytes - 1; + /* Read nodata value */ + switch (band->pixtype) { + case PT_1BB: { + band->nodataval = ((int) read_uint8(&ptr)) & 0x01; + break; + } + case PT_2BUI: { + band->nodataval = ((int) read_uint8(&ptr)) & 0x03; + break; + } + case PT_4BUI: { + band->nodataval = ((int) read_uint8(&ptr)) & 0x0F; + break; + } + case PT_8BSI: { + band->nodataval = read_int8(&ptr); + break; + } + case PT_8BUI: { + band->nodataval = read_uint8(&ptr); + break; + } + case PT_16BSI: { + band->nodataval = read_int16(&ptr, littleEndian); + break; + } + case PT_16BUI: { + band->nodataval = read_uint16(&ptr, littleEndian); + break; + } + case PT_32BSI: { + band->nodataval = read_int32(&ptr, littleEndian); + break; + } + case PT_32BUI: { + band->nodataval = read_uint32(&ptr, littleEndian); + break; + } + case PT_32BF: { + band->nodataval = read_float32(&ptr, littleEndian); + break; + } + case PT_64BF: { + band->nodataval = read_float64(&ptr, littleEndian); + break; + } + default: { + rterror("rt_raster_deserialize: Unknown pixeltype %d", band->pixtype); + for (j = 0; j <= i; j++) rt_band_destroy(rast->bands[j]); + rt_raster_destroy(rast); + return NULL; + } + } - /* Read nodata value */ - switch (band->pixtype) { - case PT_1BB: - { - band->nodataval = ((int) read_uint8(&ptr)) & 0x01; - break; - } - case PT_2BUI: - { - band->nodataval = ((int) read_uint8(&ptr)) & 0x03; - break; - } - case PT_4BUI: - { - band->nodataval = ((int) read_uint8(&ptr)) & 0x0F; - break; - } - case PT_8BSI: - { - band->nodataval = read_int8(&ptr); - break; - } - case PT_8BUI: - { - band->nodataval = read_uint8(&ptr); - break; - } - case PT_16BSI: - { - band->nodataval = read_int16(&ptr, littleEndian); - break; - } - case PT_16BUI: - { - band->nodataval = read_uint16(&ptr, littleEndian); - break; - } - case PT_32BSI: - { - band->nodataval = read_int32(&ptr, littleEndian); - break; - } - case PT_32BUI: - { - band->nodataval = read_uint32(&ptr, littleEndian); - break; - } - case PT_32BF: - { - band->nodataval = read_float32(&ptr, littleEndian); - break; - } - case PT_64BF: - { - band->nodataval = read_float64(&ptr, littleEndian); - break; - } - default: - { - rterror("rt_raster_deserialize: Unknown pixeltype %d", band->pixtype); - rtdealloc(band); - rtdealloc(rast); - return 0; - } - } + RASTER_DEBUGF(3, "rt_raster_deserialize: has nodata flag %d", band->hasnodata); + RASTER_DEBUGF(3, "rt_raster_deserialize: nodata value %g", band->nodataval); - RASTER_DEBUGF(3, "rt_raster_deserialize: has nodata flag %d", band->hasnodata); - RASTER_DEBUGF(3, "rt_raster_deserialize: nodata value %g", band->nodataval); + /* Consistency checking (ptr is pixbytes-aligned) */ + assert(!((ptr - beg) % pixbytes)); - /* Consistency checking (ptr is pixbytes-aligned) */ - assert(!((ptr - beg) % pixbytes)); + if (band->offline) { + int pathlen = 0; - if (band->offline) { - int pathlen = 0; - /* Read band number */ - band->data.offline.bandNum = *ptr; - ptr += 1; + /* Read band number */ + band->data.offline.bandNum = *ptr; + ptr += 1; - /* Register path */ - pathlen = strlen((char*) ptr); - band->data.offline.path = rtalloc(sizeof(char) * (pathlen + 1)); - if (band->data.offline.path == NULL) { - rterror("rt_raster_deserialize: Unable to allocate momory for offline band path"); - rt_band_destroy(band); - rt_raster_destroy(rast); - return NULL; - } + /* Register path */ + pathlen = strlen((char*) ptr); + band->data.offline.path = rtalloc(sizeof(char) * (pathlen + 1)); + if (band->data.offline.path == NULL) { + rterror("rt_raster_deserialize: Unable to allocate momory for offline band path"); + for (j = 0; j <= i; j++) rt_band_destroy(rast->bands[j]); + rt_raster_destroy(rast); + return NULL; + } - memcpy(band->data.offline.path, ptr, pathlen); - band->data.offline.path[pathlen] = '\0'; - ptr += pathlen + 1; + memcpy(band->data.offline.path, ptr, pathlen); + band->data.offline.path[pathlen] = '\0'; + ptr += pathlen + 1; - band->data.offline.mem = NULL; - } else { - /* Register data */ - const uint32_t datasize = rast->width * rast->height * pixbytes; - band->data.mem = (uint8_t*) ptr; - ptr += datasize; - } + band->data.offline.mem = NULL; + } + else { + /* Register data */ + const uint32_t datasize = rast->width * rast->height * pixbytes; + band->data.mem = (uint8_t*) ptr; + ptr += datasize; + } - /* Skip bytes of padding up to 8-bytes boundary */ + /* Skip bytes of padding up to 8-bytes boundary */ #if POSTGIS_DEBUG_LEVEL > 0 - const uint8_t *padbeg = ptr; + const uint8_t *padbeg = ptr; #endif - while (0 != ((ptr - beg) % 8)){ - ++ptr; - } + while (0 != ((ptr - beg) % 8)) { + ++ptr; + } - RASTER_DEBUGF(3, "rt_raster_deserialize: skip %d bytes of 8-bytes boundary padding", ptr - padbeg); + RASTER_DEBUGF(3, "rt_raster_deserialize: skip %d bytes of 8-bytes boundary padding", ptr - padbeg); - /* Consistency checking (ptr is pixbytes-aligned) */ - assert(!((ptr - beg) % pixbytes)); - } + /* Consistency checking (ptr is pixbytes-aligned) */ + assert(!((ptr - beg) % pixbytes)); + } - return rast; + return rast; } /** -- 2.40.0