Port Fix InflateBack corner case

This handles the case where a zlib user could rely on InflateBack
API to decompress content.

The NEON optimization assumes that it can perform wide stores, sometimes
overwriting data on the output pointer (but never overflowing the buffer
end as it has enough room for the write).

For infback there is no such guarantees (i.e. no extra wiggle room),
which can result in illegal operations. This patch fixes the potential
issue by falling back to the non-optimized code for such cases.

Also it adds some comments about the entry assumptions in inflate and
writes out a defined value at the write buffer to identify where
the real data has ended (helpful while debugging).

For reference, please see:
0bb1104079

Change-Id: Iffbda9eb5e08a661aa15c6e3d1c59b678cc23b2c
This commit is contained in:
Adenilson Cavalcanti 2018-04-04 15:14:57 -07:00
parent 390b2713be
commit 267e6f2017
4 changed files with 33 additions and 8 deletions

View File

@ -139,9 +139,8 @@ if(CMAKE_COMPILER_IS_GNUCC)
if(ARM_NEON)
list(REMOVE_ITEM ZLIB_SRCS inflate.c)
list(REMOVE_ITEM ZLIB_SRCS inffast.c)
set(ZLIB_ARM_NEON_HDRS contrib/arm/chunkcopy.h)
set(ZLIB_ARM_NEON contrib/arm/inflate.c contrib/arm/inffast.c)
set(ZLIB_ARM_NEON_HDRS contrib/arm/chunkcopy.h contrib/arm/inffast_chunk.h)
set(ZLIB_ARM_NEON contrib/arm/inflate.c contrib/arm/inffast_chunk.c)
add_definitions(-DARM_NEON)
set(COMPILER ${CMAKE_C_COMPILER})
# NEON is mandatory in ARMv8.

View File

@ -6,8 +6,8 @@
#include "zutil.h"
#include "inftrees.h"
#include "inflate.h"
#include "inffast.h"
#include "chunkcopy.h"
#include "contrib/arm/inffast_chunk.h"
#include "contrib/arm/chunkcopy.h"
#ifdef ASMINF
# pragma message("Assembler code may have bugs -- use at your own risk")
@ -28,6 +28,10 @@
strm->avail_out >= 258
start >= strm->avail_out
state->bits < 8
strm->next_out[0..strm->avail_out] does not overlap with
strm->next_in[0..strm->avail_in]
strm->state->window is allocated with an additional
CHUNKCOPY_CHUNK_SIZE-1 bytes of padding beyond strm->state->wsize
On return, state->mode is one of:
@ -48,7 +52,7 @@
requires strm->avail_out >= 258 for each loop to avoid checking for
output space.
*/
void ZLIB_INTERNAL inflate_fast(strm, start)
void ZLIB_INTERNAL inflate_fast_chunk(strm, start)
z_streamp strm;
unsigned start; /* inflate()'s starting value for strm->avail_out */
{

View File

@ -0,0 +1,12 @@
/* inffast.h -- header to use inffast.c
* Copyright (C) 1995-2003, 2010 Mark Adler
* Copyright (C) 2017 ARM, Inc.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
void ZLIB_INTERNAL inflate_fast_chunk OF((z_streamp strm, unsigned start));

View File

@ -83,7 +83,7 @@
#include "zutil.h"
#include "inftrees.h"
#include "inflate.h"
#include "inffast.h"
#include "contrib/arm/inffast_chunk.h"
#include "contrib/arm/chunkcopy.h"
#ifdef MAKEFIXED
@ -1056,7 +1056,7 @@ int flush;
case LEN:
if (have >= 6 && left >= 258) {
RESTORE();
inflate_fast(strm, out);
inflate_fast_chunk(strm, out);
LOAD();
if (state->mode == TYPE)
state->back = -1;
@ -1262,6 +1262,16 @@ int flush;
Note: a memory error from inflate() is non-recoverable.
*/
inf_leave:
/* We write a defined value in the unused space to help mark
* where the stream has ended. We don't use zeros as that can
* mislead clients relying on undefined behavior (i.e. assuming
* that the data is over when the buffer has a zero/null value).
*/
if (left >= CHUNKCOPY_CHUNK_SIZE)
memset(put, 0x55, CHUNKCOPY_CHUNK_SIZE);
else
memset(put, 0x55, left);
RESTORE();
if (state->wsize || (out != strm->avail_out && state->mode < BAD &&
(state->mode < CHECK || flush != Z_FINISH)))