diff options
author | Stephan Bergmann <sbergman@redhat.com> | 2019-06-18 00:00:54 +0200 |
---|---|---|
committer | Stephan Bergmann <sbergman@redhat.com> | 2019-06-18 10:59:59 +0200 |
commit | 42c0e433aca68c669bc0f55af404b6bae1655fba (patch) | |
tree | b9aca1e8f0c6c16d8070e46afc1aca689c0e609c /vcl/source | |
parent | a2e4b76e29e491bac4f9e6dfd9929dfd49a4b05e (diff) |
Avoid -fsanitize=misaligned-pointer-use
...like
> vcl/source/filter/jpeg/Exif.cxx:158:31: runtime error: member access within misaligned address 0x624000a5610a for type 'Exif::ExifIFD', which requires 4 byte alignment
> 0x624000a5610a: note: pointer points here
> 00 00 00 07 01 12 00 03 00 00 00 01 00 01 00 00 01 1a 00 05 00 00 00 01 00 00 00 62 01 1b 00 05
> ^
> #0 in Exif::processIFD(unsigned char*, unsigned short, unsigned short, unsigned short, bool, bool) at vcl/source/filter/jpeg/Exif.cxx:158:31
> #1 in Exif::processExif(SvStream&, unsigned short, bool) at vcl/source/filter/jpeg/Exif.cxx:255:5
> #2 in Exif::processJpeg(SvStream&, bool) at vcl/source/filter/jpeg/Exif.cxx:132:20
[...]
when inserting some .jpg into Draw.
The swapping in Exif::processIFD had been introduced with
3ad12d1a540eeb54fbb34afc3b7a76bf9e3207c3 "fdo#57659: fix exif processing", and
it had probably been an oversight that it used OSL_SWAPWORD instead of
OSL_SWAPDWORD to swap sal_uInt32 ifd->offset (in two places), and that it failed
to swap ifd->type and ifd->count in the bSetValue branch (see the discussion at
<https://gerrit.libreoffice.org/#/c/6245/> "fdo#57659: fix exif processing").
Change-Id: If40ddb9b1ef4e2ffc08a0899920919989e8cdfdc
Reviewed-on: https://gerrit.libreoffice.org/74236
Tested-by: Jenkins
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
Diffstat (limited to 'vcl/source')
-rw-r--r-- | vcl/source/filter/jpeg/Exif.cxx | 73 | ||||
-rw-r--r-- | vcl/source/filter/jpeg/Exif.hxx | 10 |
2 files changed, 59 insertions, 24 deletions
diff --git a/vcl/source/filter/jpeg/Exif.cxx b/vcl/source/filter/jpeg/Exif.cxx index 3b014f6deb1d..187d5ac6efc6 100644 --- a/vcl/source/filter/jpeg/Exif.cxx +++ b/vcl/source/filter/jpeg/Exif.cxx @@ -148,38 +148,73 @@ bool Exif::processJpeg(SvStream& rStream, bool bSetValue) return false; } -void Exif::processIFD(sal_uInt8* pExifData, sal_uInt16 aLength, sal_uInt16 aOffset, sal_uInt16 aNumberOfTags, bool bSetValue, bool bSwap) +namespace { + +sal_uInt16 read16(sal_uInt8 const * data, bool littleEndian) { + if (littleEndian) { + return data[0] | (sal_uInt16(data[1]) << 8); + } else { + return data[1] | (sal_uInt16(data[0]) << 8); + } +} + +void write16(sal_uInt16 value, sal_uInt8 * data, bool littleEndian) { + if (littleEndian) { + data[0] = value & 0xFF; + data[1] = value >> 8; + } else { + data[1] = value & 0xFF; + data[0] = value >> 8; + } +} + +sal_uInt32 read32(sal_uInt8 const * data, bool littleEndian) { + if (littleEndian) { + return data[0] | (sal_uInt32(data[1]) << 8) + | (sal_uInt32(data[2]) << 16) | (sal_uInt32(data[3]) << 24); + } else { + return data[3] | (sal_uInt32(data[2]) << 8) + | (sal_uInt32(data[1]) << 16) | (sal_uInt32(data[0]) << 24); + } +} + +void write32(sal_uInt32 value, sal_uInt8 * data, bool littleEndian) { + if (littleEndian) { + data[0] = value & 0xFF; + data[1] = (value >> 8) & 0xFF; + data[2] = (value >> 16) & 0xFF; + data[3] = value >> 24; + } else { + data[3] = value & 0xFF; + data[2] = (value >> 8) & 0xFF; + data[1] = (value >> 16) & 0xFF; + data[0] = value >> 24; + } +} + +} + +void Exif::processIFD(sal_uInt8* pExifData, sal_uInt16 aLength, sal_uInt16 aOffset, sal_uInt16 aNumberOfTags, bool bSetValue, bool littleEndian) { ExifIFD* ifd = nullptr; while (aOffset <= aLength - 12 && aNumberOfTags > 0) { ifd = reinterpret_cast<ExifIFD*>(&pExifData[aOffset]); - sal_uInt16 tag = ifd->tag; - if (bSwap) - { - tag = OSL_SWAPWORD(ifd->tag); - } + sal_uInt16 tag = read16(ifd->tag, littleEndian); if (tag == ORIENTATION) { if(bSetValue) { - ifd->tag = ORIENTATION; - ifd->type = 3; - ifd->count = 1; - ifd->offset = maOrientation; - if (bSwap) - { - ifd->tag = OSL_SWAPWORD(ifd->tag); - ifd->offset = OSL_SWAPWORD(ifd->offset); - } + write16(ORIENTATION, ifd->tag, littleEndian); + write16(3, ifd->type, littleEndian); + write32(1, ifd->count, littleEndian); + write32(maOrientation, ifd->offset, littleEndian); } else { - sal_uInt32 nIfdOffset = ifd->offset; - if (bSwap) - nIfdOffset = OSL_SWAPWORD(ifd->offset); + sal_uInt32 nIfdOffset = read32(ifd->offset, littleEndian); maOrientation = convertToOrientation(nIfdOffset); } } @@ -252,7 +287,7 @@ bool Exif::processExif(SvStream& rStream, sal_uInt16 aSectionLength, bool bSetVa aNumberOfTags = ((aExifData[aOffset] << 8) | aExifData[aOffset+1]); } - processIFD(aExifData.get(), aLength, aOffset+2, aNumberOfTags, bSetValue, bSwap); + processIFD(aExifData.get(), aLength, aOffset+2, aNumberOfTags, bSetValue, bIntel); if (bSetValue) { diff --git a/vcl/source/filter/jpeg/Exif.hxx b/vcl/source/filter/jpeg/Exif.hxx index 6b5991c60ee7..046df028a891 100644 --- a/vcl/source/filter/jpeg/Exif.hxx +++ b/vcl/source/filter/jpeg/Exif.hxx @@ -49,13 +49,13 @@ private: bool processJpeg(SvStream& rStream, bool bSetValue); bool processExif(SvStream& rStream, sal_uInt16 aLength, bool bSetValue); - void processIFD(sal_uInt8* pExifData, sal_uInt16 aLength, sal_uInt16 aOffset, sal_uInt16 aNumberOfTags, bool bSetValue, bool bMoto); + void processIFD(sal_uInt8* pExifData, sal_uInt16 aLength, sal_uInt16 aOffset, sal_uInt16 aNumberOfTags, bool bSetValue, bool bLittleEndian); struct ExifIFD { - sal_uInt16 tag; - sal_uInt16 type; - sal_uInt32 count; - sal_uInt32 offset; + sal_uInt8 tag[2]; + sal_uInt8 type[2]; + sal_uInt8 count[4]; + sal_uInt8 offset[4]; }; struct TiffHeader { |