Bug Summary

File:external/xstream/src/z.cpp
Location:line 494, column 13
Description:Value stored to 'cret' is never read

Annotated Source Code

1#include <xstream/config.h>
2
3#if HAVE_LIBZ1
4
5#include <algorithm>
6#include <string.h>
7#include <string>
8
9#include <xstream/z.h>
10#include <xstream/except/z.h>
11#include <stdexcept>
12
13#include <stdio.h>
14#include <zlib.h>
15#include <arpa/inet.h>
16
17#include <cassert>
18
19#include "debug.h"
20
21#define COMPRESSION_BLOCK_SIZE32000 32000
22
23namespace xstream {
24namespace z {
25
26// define the standard header for a zlib stream that can be used
27// to prime the inflate engine to start at an arbitrary block in
28// an input stream
29
30 static int z_header_length = 2;
31 static unsigned char z_header[2] = {0x78, 0x9c};
32
33 struct pimpl: public z_stream {};
34
35 static const int eof = std::streambuf::traits_type::eof();
36
37 static inline int flush_macro(const flush_kind f) {
38 switch (f) {
39 case no_sync:
40 return Z_NO_FLUSH0;
41 case normal_sync:
42 return Z_SYNC_FLUSH2;
43 case full_sync:
44 return Z_FULL_FLUSH3;
45 case finish_sync:
46 return Z_FINISH4;
47 case block_sync:
48#ifndef Z_BLOCK5
49# define Z_BLOCK5 5
50#endif
51 return Z_BLOCK5;
52 default:
53 //should probably throw
54 return Z_NO_FLUSH0;
55 }
56 }
57
58 const char* error_str(int err) {
59 switch(err) {
60 case Z_MEM_ERROR(-4):
61 return "out of memory";
62 case Z_VERSION_ERROR(-6):
63 return "zlib version mismatch";
64 case Z_DATA_ERROR(-3):
65 return "invalid or incomplete data";
66 case Z_STREAM_ERROR(-2):
67 return "stream error";
68 case Z_NEED_DICT2:
69 return "need dictionary";
70 case Z_STREAM_END1:
71 return "stream end";
72 case Z_BUF_ERROR(-5):
73 return "buffer error";
74 }
75
76 return "unknown error";
77 }
78
79
80 common::common(std::streambuf * sb)
81 : xstream::common_buffer(sb), z_strm(0), block_offset(0)
82 {
83 LOG("z::common");
84
85 z_strm = new pimpl;
86
87 //initialize zlib structure
88 z_strm->zalloc = Z_NULL0;
89 z_strm->zfree = Z_NULL0;
90 z_strm->opaque = Z_NULL0;
91 //buffers
92 z_strm->avail_out = out.size;
93 z_strm->next_out = reinterpret_cast < Bytef* >(out.buf);
94
95 z_strm->avail_in = 0;
96 z_strm->next_in = reinterpret_cast < Bytef* >(in.buf);
97
98 }
99
100 void common::grow_out (unsigned int factor) {
101
102 const size_t taken = out.size - z_strm->avail_out;
103
104 out.grow(factor);
105
106 z_strm->next_out = reinterpret_cast < Bytef* >(out.buf + taken);
107 z_strm->avail_out = out.size - taken;
108 }
109
110 unsigned long int common::input_count() const {
111 return z_strm->total_in;
112 }
113
114 unsigned long int common::output_count() const {
115 return z_strm->total_out;
116 }
117
118 unsigned long int common::checksum() const {
119 return z_strm->adler;
120 }
121
122 common::~common() {
123 LOG("z::~common");
124 delete z_strm;
125 }
126
127 ostreambuf::ostreambuf (std::streambuf * sb)
128 : common(sb), level(Z_DEFAULT_COMPRESSION(-1)) {
129 LOG("z::ostreambuf without compression level");
130 init();
131 }
132
133 ostreambuf::ostreambuf(std::streambuf *sb, int l)
134 : common(sb), level (l) {
135 LOG ("z::ostreambuf with compression level " << l);
136 init();
137 }
138
139 void ostreambuf::raise_error(int err) {
140 std::string what = error_str(err);
141
142 LOG("z::ostreambuf::raise_error (" << err << ") = " << what);
143
144 if (what.size() > 0) {
145 throw compress_error(this, what);
146 } else {
147 throw compress_error(this);
148 }
149 }
150
151 void ostreambuf::init() {
152 LOG ("z::ostreambuf::init");
153
154 if (Z_DEFAULT_COMPRESSION(-1) == level || (level <= 9 && level >= 1)) {
155 int cret =::deflateInit(z_strm, level)deflateInit_((z_strm), (level), "1.2.3", sizeof(z_stream));
156
157 if (Z_OK0 != cret) {
158 LOG ("z::ostreambuf::init: error creating zstream " << cret);
159 //XXX exception ins constructor
160 raise_error(cret);
161 }
162 //initialize streambuf interface functions
163 setp(in.buf, in.buf + in.size);
164 } else {
165 char str[256];
166 sprintf(str, "invalid compression level %d", level);
167 throw std::domain_error(str);
168 }
169 }
170
171 ostreambuf::~ostreambuf() {
172 LOG ("z::ostreambuf::~ostreambuf");
173 //sync (write remaining data)
174 flush(finish_sync);
175
176 //sync underlying streambuf
177 _sb->pubsync();
178
179 if (0 != z_strm) {
180 //XXX should I throw an exception in case of error?
181 //remember this is a destructor
182 //I should definitly LOG something
183 int cret = ::deflateEnd(z_strm);
184 if (Z_OK0 != cret){
185 LOG("z::~ostreambuf error dealocating zstream");
186 }
187 }
188 }
189
190 int ostreambuf::sync () {
191 LOG ("z::ostreambuf::sync");
192 int ret = flush(normal_sync);
193 _sb->pubsync();
194 return ret;
195 }
196
197
198 int ostreambuf::overflow(int c) {
199 LOG ("z::ostreambuf::overflow(" << c << ")\t available=" << (available ()) << "\tEOF=" << eof);
200 if (eof == c) {
201 LOG ("\tEOF");
202 flush(no_sync);
203 return eof;
204 } else {
205 if (0 == available ()) {
206 LOG ("\t have to flush :[]");
207 flush(no_sync);
208 }
209 *pptr () = static_cast < char >(c);
210 pbump (1);
211 }
212 return c;
213 }
214
215 std::streamsize ostreambuf::xsputn (const char *buffer, std::streamsize n) {
216 LOG ("z::ostreambuf::xsputn(" << buffer << "," << n << ")");
217
218 return flush(no_sync, buffer, n);
219 }
220
221 int ostreambuf::flush(flush_kind f, const char *appendbuf, int appendsize) {
222 LOG ("z::ostreambuf::flush(" << f << ")");
223 std::streamsize in_s = taken ();
224 LOG ("\tinput_size=" << in_s);
225
226 //set up compression engine input feed
227 int written;
228 if (in_s > 0) {
229 z_strm->next_in = reinterpret_cast < Bytef* >(pbase());
230 z_strm->avail_in = in_s;
231 written = in_s;
232 } else if (appendsize > 0) {
233 z_strm->next_in = (Bytef*)appendbuf;
234 z_strm->avail_in = appendsize;
235 written = appendsize;
236 appendsize = 0;
237 } else {
238 z_strm->next_in = reinterpret_cast < Bytef* >(pbase());
239 z_strm->avail_in = 0;
240 written = 0;
241 }
242 block_offset += written;
243 if (block_offset > (std::streamoff)COMPRESSION_BLOCK_SIZE32000) {
244 f = (f == no_sync)? full_sync : f;
245 }
246
247 bool redo = false;
248
249 do {
250 int cret;
251 redo = false;
252
253 do {
254 cret = ::deflate(z_strm, flush_macro(f));
255
256 if (finish_sync == f && Z_OK0 == cret) {
257 grow_out();
258 continue;
259 } else {
260 break;
261 }
262 } while (1);
263
264 //error handling
265 if (f == finish_sync) {
266 if (Z_STREAM_END1 != cret) {
267 //serious error, throw exception
268 LOG ("\terror :" << cret);
269 }
270 } else if (Z_OK0 != cret) {
271 LOG ("\terror deflating " << cret);
272 //XXX throw exception here
273 raise_error(cret);
274 }
275
276 if (f != no_sync) {
277 std::streamsize count = out.size - z_strm->avail_out;
278 LOG ("\twriting " << count << " bytes");
279 int size = htonl(count)(__extension__ ({ register unsigned int __v, __x = (count); if
(__builtin_constant_p (__x)) __v = ((((__x) & 0xff000000
) >> 24) | (((__x) & 0x00ff0000) >> 8) | (((__x
) & 0x0000ff00) << 8) | (((__x) & 0x000000ff) <<
24)); else __asm__ ("bswap %0" : "=r" (__v) : "0" (__x)); __v
; }))
;
280 const std::streamsize wrote = _sb->sputn((char*)&size, 4) +
281 _sb->sputn(out.buf, count);
282 if (wrote != count + 4) {
283 LOG("\terror writting, only wrote " << wrote
284 << " but asked for " << count);
285 raise_error(Z_STREAM_ERROR(-2));
286 }
287
288 // reset output
289 z_strm->next_out = reinterpret_cast < Bytef* >(out.buf);
290 z_strm->avail_out = out.size;
291 block_offset = 0;
292 }
293
294 if (0 == z_strm->avail_out) { // && 0 != z_strm->avail_in)
295 LOG("\tavail_out=0 => redo");
296 redo = true;
297 }
298
299 if (!redo && appendbuf && appendsize > 0) {
300 z_strm->next_in = (Bytef*)appendbuf;
301 z_strm->avail_in = appendsize;
302 written += appendsize;
303 appendsize = 0;
304 redo = true;
305 }
306 }
307 while (redo);
308 assert (0 == z_strm->avail_in)((0 == z_strm->avail_in) ? static_cast<void> (0) : __assert_fail
("0 == z_strm->avail_in", "external/xstream/src/z.cpp", 308
, __PRETTY_FUNCTION__))
;
309 //reset buffer
310 setp(in.buf, in.buf + in.size);
311 return written;
312 }
313
314 /////////////////////
315 // istream follows //
316 /////////////////////
317
318 istreambuf::istreambuf (std::streambuf * sb)
319 : common(sb), end(false), block_size(0) {
320 LOG ("z::istreambuf");
321
322 int cret = ::inflateInit(z_strm)inflateInit_((z_strm), "1.2.3", sizeof(z_stream));
323
324 if (Z_OK0 != cret) {
325 LOG ("\terror creating zstream " << cret);
326 //XXX throw exception here
327 raise_error(cret);
328 }
329 //initialize streambuf interface functions
330 //first call will call uflow and this will set the buffer accordingly
331 //no buffering
332 setg(out.buf, out.buf, out.buf);
333 }
334
335 void istreambuf::raise_error(int err) {
336 std::string what = error_str(err);
337
338 LOG("z::istreambuf::raise_error (" << err << ") = " << what);
339
340 if (what.size() > 0) {
341 throw decompress_error(this, what);
342 } else {
343 throw decompress_error(this);
344 }
345 }
346
347 int istreambuf::underflow() {
348 LOG("z:istreambuf::underflow");
349
350 if (end) {
351 LOG("\tend of stream (EOF)");
352 //signal the stream has reached it's end
353 return eof;
354 }
355
356 z_strm->avail_out = out.size;
357 z_strm->next_out = reinterpret_cast < Bytef* >(out.buf);
358
359 if (0 < z_strm->avail_in) {
360 LOG("\tdata in queue, inflating");
361 inflate();
362 }
363 while (!end && z_strm->avail_out > 0) {
364 read_inflate();
365 }
366 if (end && z_strm->avail_out > 0) {
367 LOG("\tend of stream (EOF)");
368 //signal the stream has reached it's end
369 return eof;
370 }
371
372 //set streambuf pointers
373 setg(out.buf, out.buf, reinterpret_cast <char*> (z_strm->next_out) );
374
375 return int(out.buf[0]);
376 }
377
378 //read to buffer in place (apart from data already buffered)
379 std::streamsize istreambuf::xsgetn(char *buffer, std::streamsize n) {
380 LOG("z::istreambuf::xsgetn (" << n << ")");
381
382 //try to satisfy request from buffered input
383 std::streamsize available = egptr() - gptr();
384 int read = (available >= n)? n : available;
385 if (read) {
386 std::copy(gptr(), gptr() + read, buffer);
387 gbump(read);
388 block_offset += read;
389 }
390
391 //inflate the rest directly into the user's buffer
392 if (read < n) {
393 if (end) {
394 LOG("\tend of stream (EOF)");
395 //signal the stream has reached it's end
396 return eof;
397 }
398
399 z_strm->next_out = reinterpret_cast < Bytef* >(buffer) + read;
400 z_strm->avail_out = n - read;
401
402 if (0 < z_strm->avail_in) {
403 inflate();
404 }
405 while (!end && z_strm->avail_out > 0) {
406 read_inflate();
407 }
408 if (end && z_strm->avail_out > 0) {
409 LOG("\tend of stream (EOF)");
410 //signal the stream has reached it's end
411 return eof;
412 }
413 block_offset += n - read;
414 }
415 return n;
416 }
417
418 void istreambuf::read_inflate( const flush_kind f) {
419 LOG("z::istreambuf::read_inflate " << f);
420 int read;
421 int block_pending = 0;
422 if (block_size < 0) { // stream has no blocksize markers
423 read = _sb->sgetn(in.buf, in.size);
424 }
425 else { // look for prefixed blocksize: leading byte = 0
426 read = _sb->sgetn(in.buf, 4);
427 if (read < 4) {
428 end = true;
429 return;
430 }
431 if (in.buf[0] == 0) { // z blocks have prefixed blocksize
432 int *size = (int*)in.buf;
433 block_pending = ntohl(*size)(__extension__ ({ register unsigned int __v, __x = (*size); if
(__builtin_constant_p (__x)) __v = ((((__x) & 0xff000000
) >> 24) | (((__x) & 0x00ff0000) >> 8) | (((__x
) & 0x0000ff00) << 8) | (((__x) & 0x000000ff) <<
24)); else __asm__ ("bswap %0" : "=r" (__v) : "0" (__x)); __v
; }))
;
434 read = _sb->sgetn(in.buf, block_pending);
435 }
436 else { // z blocks are jammed together, no blocksize available
437 read += _sb->sgetn(in.buf + 4, in.size - 4);
438 block_size = -1;
439 }
440 }
441 LOG("\tread " << read << " bytes");
442 block_offset = 0;
443
444 if (0 == read) {
445 end = true;
446 return;
447 }
448
449 // We want to be able to start decompression at an arbitrary position
450 // in the input stream. This is possible with bzip2 streams, but there
451 // is a problem that the compressed blocks are arbitrary numbers of
452 // bits long and they are catenated one after another in a bit stream
453 // without any reference to byte boundaries. This makes it difficult
454 // to jump into the middle of a stream and start the decompressor
455 // since it expects a stream header followed by the first block that
456 // happens to start on a byte boundary. To make this work, I splice
457 // an artificial stream header followed by a dummy compressed block
458 // onto the beginning of the input stream, where the length of the
459 // dummy block in bits is chosen so that it abutts without padding
460 // the next block in the input stream. I have prepared 8 dummy blocks
461 // so there should be one to match the alignment of any input block.
462 // To match them, I look for the first place in the input stream
463 // with a byte string that matches the last 5 bytes in one of my
464 // dummy headers, and then I inject the dummy header into the
465 // decompressor ahead of the actual data. The dummy blocks are all
466 // contrived to decompress to an 8-byte string, so throwing away the
467 // first 8 bytes out of the decompressor, it is primed to decompress
468 // the remaining stream without any need for bit-shifting the input.
469
470 const char* head = (const char*)z_header;
471 if (block_size == 0 && strncmp(head, in.buf, z_header_length) != 0) {
472 z_strm->avail_in = z_header_length;
473 z_strm->next_in = reinterpret_cast < Bytef* >(z_header);
474 inflate(f); // inject the z stream header
475 }
476 block_size = read;
477 z_strm->next_in = reinterpret_cast < Bytef* >(in.buf);
478 z_strm->avail_in = read;
479 inflate(f);
480 }
481
482 void istreambuf::inflate(const flush_kind f) {
483 LOG("z::istreambuf::inflate " << f);
484
485 int cret = ::inflate(z_strm, flush_macro(f));
486
487 if (Z_STREAM_END1 == cret) {
488 end = true;
489 }
490 else if (cret == Z_DATA_ERROR(-3) && z_strm->avail_in == 0) {
491 // Ignore CRC errors at the end of stream because we may not have
492 // started decompressing at the beginning. We can rely on the CRC
493 // checks that are present within each compressed block anyway.
494 cret = Z_OK0;
Value stored to 'cret' is never read
495 end = true;
496 }
497 else if (Z_OK0 != cret) {
498 LOG("\terror inflating: " << cret);
499 //XXX throw exception
500 raise_error(cret);
501 //can try to salvage some more data with inflateSync (on some cases)
502 }
503 }
504
505 istreambuf::~istreambuf() {
506 LOG("z::~istreambuf");
507 if (0 != z_strm) {
508 //XXX should I throw an exception in case of error?
509 //remember this is a destructor
510 ::inflateEnd(z_strm);
511 }
512 }
513
514}//namespace z
515}//namespace xstream
516
517#endif //zlib