From baf78fc04a91a509fd7f0b23d98476e86709a2f6 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Sun, 31 May 2015 18:17:26 +0100 Subject: [PATCH] oops, fix base64 encode/decode padding we were adding up to two bytes of null to the end of base64-encoded binary data due to a signed/unsigned mixup add a test for this, plus a test for vips file format --- ChangeLog | 1 + TODO | 18 ------------------ libvips/iofuncs/base64.c | 21 +++++++++++++-------- test/test_foreign.py | 1 + 4 files changed, 15 insertions(+), 26 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1b7ccbee..887f8456 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,7 @@ - vipsthumbnail uses vips_premultiply() for better alpha quality - vips_copy() can turn 1xN or Nx1 M-band images into MxN one-band images - added bandand() bandor() bandeor() convenience funcs to Python +- oops, base64 encode could pad by up to two zero bytes 7/5/15 started 8.0.3 - dzsave and tif pyr write could fail for some image dimensions, thanks Jonas diff --git a/TODO b/TODO index dd46da2d..1e1ac37e 100644 --- a/TODO +++ b/TODO @@ -1,21 +1,3 @@ -- extra character in exif-data? - - try: - - $ cd test - $ vipsheader -a images/IMG_4618.jpg | grep exif-data - exif-data: VIPS_TYPE_BLOB, data = 0x16e0a20, length = 6626 - $ vips copy images/IMG_4618.jpg x.v - $ vipsheader -a x.v | grep exif-data - exif-data: VIPS_TYPE_BLOB, data = 0x20679f0, length = 6627 - - one byte longer! - - fix, and add a test for exif length to test/test_foreign.py - - - - - how about something like vips_grid() which turns a tall thin one-band image into a much smaller many-band image? diff --git a/libvips/iofuncs/base64.c b/libvips/iofuncs/base64.c index d192bc5a..ab2c9a0f 100644 --- a/libvips/iofuncs/base64.c +++ b/libvips/iofuncs/base64.c @@ -64,6 +64,9 @@ Modified on: 25/3/11 - move to vips_ namespace +31/5/15 + - oops siged/unsignned mess-up meant we were not padding correctly + */ /* @@ -112,7 +115,7 @@ static unsigned char b64_index[256] = { * end up with in[2] in the bottom few bits. */ static int -read24( const unsigned char *in, size_t remaining ) +read24( const unsigned char *in, int remaining ) { int bits; int i; @@ -132,12 +135,12 @@ read24( const unsigned char *in, size_t remaining ) /* Output (up to) 24 bits as four base64 chars. Pad with '=' characters. */ static void -encode24( char *p, int bits, size_t remaining ) +encode24( char *p, int bits, int remaining ) { int i; for( i = 0; i < 4; i++ ) { - if( remaining == 0 ) + if( remaining <= 0 ) p[i] = '='; else { /* Take the top 6 bits of 24. @@ -162,7 +165,7 @@ vips__b64_encode( const unsigned char *data, size_t data_length ) char *buffer; char *p; - size_t i; + int i; int cursor; if( data_length == 0 ) { @@ -170,7 +173,8 @@ vips__b64_encode( const unsigned char *data, size_t data_length ) return( NULL ); } if( output_data_length > 1024 * 1024 ) { - /* We shouldn't really be used for large amounts of data. + /* We shouldn't really be used for large amounts of data, plus + * we are using int offsets. */ vips_error( "vips__b64_encode", "%s", _( "too much data" ) ); return( NULL ); @@ -183,7 +187,7 @@ vips__b64_encode( const unsigned char *data, size_t data_length ) cursor = 0; for( i = 0; i < data_length; i += 3 ) { - size_t remaining = data_length - i; + int remaining = data_length - i; int bits; bits = read24( data + i, remaining ); @@ -232,10 +236,11 @@ vips__b64_decode( const char *buffer, size_t *data_length ) unsigned char *p; unsigned int bits; int nbits; - size_t i; + int i; if( output_data_length > 1024 * 1024 ) { - /* We shouldn't really be used for large amounts of data. + /* We shouldn't really be used for large amounts of data, plus + * we are using an int for offset. */ vips_error( "vips__b64_decode", "%s", _( "too much data" ) ); return( NULL ); diff --git a/test/test_foreign.py b/test/test_foreign.py index ad116c02..96d1e1d1 100755 --- a/test/test_foreign.py +++ b/test/test_foreign.py @@ -113,6 +113,7 @@ class TestForeign(unittest.TestCase): before_exif = self.colour.get_value("exif-data") after_exif = x.get_value("exif-data") + self.assertEqual(len(before_exif), len(after_exif)) for i in range(len(before_exif)): self.assertEqual(before_exif[i], after_exif[i])