case DUMP_RESULT:
initialize();
- cache_dump(optarg, stdout);
+ if (!cache_dump(optarg, stdout)) {
+ fprintf(stderr, "Error: Corrupt result file\n");
+ return 1;
+ }
break;
case HASH_FILE:
return fwrite(data, 1, size, output) == size;
}
-static void
+static bool
compr_none_free(struct compr_state *handle)
{
- (void)handle;
+ FILE *output = (FILE *)handle;
+ return ferror(output) == 0;
}
struct compressor compr_none = {
{
FILE *output;
z_stream stream;
+ bool failed;
};
static struct compr_state *
state->stream.zalloc = Z_NULL;
state->stream.zfree = Z_NULL;
state->stream.opaque = Z_NULL;
+ state->failed = false;
int ret = deflateInit(&state->stream, level);
if (ret != Z_OK) {
static bool
compr_zlib_write(struct compr_state *handle, const void *data, size_t size)
{
+ if (!handle) {
+ return false;
+ }
struct state *state = (struct state *)handle;
state->stream.next_in = (const Bytef *)data;
unsigned int compressed_bytes = sizeof(buffer) - state->stream.avail_out;
if (fwrite(buffer, 1, compressed_bytes, state->output) != compressed_bytes
|| ferror(state->output)) {
+ state->failed = true;
return false;
}
} while (state->stream.avail_out == 0);
return true;
}
-static void
+static bool
compr_zlib_free(struct compr_state *handle)
{
+ if (!handle) {
+ return false;
+ }
struct state *state = (struct state *)handle;
compr_zlib_write(handle, NULL, 0);
deflateEnd(&state->stream);
+ bool success = !state->failed;
free(state);
+ return success;
}
struct compressor compr_zlib = {
struct compressor {
struct compr_state *(*init)(FILE *output, int compression_level);
bool (*write)(struct compr_state *state, const void *data, size_t size);
- void (*free)(struct compr_state *state);
+ bool (*free)(struct compr_state *state);
};
struct decompr_state;
struct decompressor {
struct decompr_state *(*init)(FILE *input);
bool (*read)(struct decompr_state *state, void *data, size_t size);
- void (*free)(struct decompr_state *state);
+ bool (*free)(struct decompr_state *state);
};
extern struct compressor compr_none;
return fread(data, 1, size, input) == size;
}
-static void decompr_none_free(struct decompr_state *handle)
+static bool
+decompr_none_free(struct decompr_state *handle)
{
- (void)handle;
+ FILE *input = (FILE *)handle;
+ return ferror(input) == 0;
}
struct decompressor decompr_none = {
#include <zlib.h>
+enum stream_state {
+ STREAM_STATE_READING,
+ STREAM_STATE_FAILED,
+ STREAM_STATE_END
+};
+
struct state
{
FILE *input;
size_t input_size;
size_t input_consumed;
z_stream stream;
+ enum stream_state stream_state;
};
static struct decompr_state *
state->stream.opaque = Z_NULL;
state->stream.avail_in = 0;
state->stream.next_in = Z_NULL;
+ state->stream_state = STREAM_STATE_READING;
int ret = inflateInit(&state->stream);
if (ret != Z_OK) {
static bool
decompr_zlib_read(struct decompr_state *handle, void *data, size_t size)
{
+ if (!handle) {
+ return false;
+ }
struct state *state = (struct state *)handle;
size_t bytes_read = 0;
state->input_size = fread(
state->input_buffer, 1, sizeof(state->input_buffer), state->input);
if (state->input_size == 0) {
+ state->stream_state = STREAM_STATE_FAILED;
return false;
}
state->input_consumed = 0;
case Z_NEED_DICT:
case Z_DATA_ERROR:
case Z_MEM_ERROR:
+ state->stream_state = STREAM_STATE_FAILED;
return false;
+ case Z_STREAM_END:
+ state->stream_state = STREAM_STATE_END;
+ break;
}
bytes_read = size - state->stream.avail_out;
state->input_consumed = state->input_size - state->stream.avail_in;
return true;
}
-static void decompr_zlib_free(struct decompr_state *handle)
+static bool decompr_zlib_free(struct decompr_state *handle)
{
+ if (!handle) {
+ return false;
+ }
struct state *state = (struct state *)handle;
inflateEnd(&state->stream);
+ bool success = state->stream_state == STREAM_STATE_END;
free(handle);
+ return success;
}
struct decompressor decompr_zlib = {
}
decompr_state = decompressor->init(f);
+ if (!decompr_state) {
+ cc_log("Failed to initialize decompressor");
+ goto out;
+ }
if (dump_stream) {
const uint8_t compr_level = header[6];
if (subfile) {
fclose(subfile);
}
- if (decompressor) {
- decompressor->free(decompr_state);
+ if (decompressor && !decompressor->free(decompr_state)) {
+ success = false;
}
if (f) {
fclose(f);
compressor = &compr_zlib;
}
- struct compr_state *compr_state =
- compressor->init(f, compression_level);
- bool ok = write_cache(l, compressor, compr_state);
- compressor->free(compr_state);
+ struct compr_state *compr_state = compressor->init(f, compression_level);
+ if (!compr_state) {
+ cc_log("Failed to initialize compressor");
+ goto out;
+ }
+ bool ok = write_cache(l, compressor, compr_state)
+ && compressor->free(compr_state);
if (!ok) {
cc_log("Failed to write cache file");
goto out;
CHECK(compr_zlib.write(c_state, "foobar", 6));
- compr_zlib.free(c_state);
+ CHECK(compr_zlib.free(c_state));
fclose(f);
f = fopen("data.zlib", "r");
// Nothing left to read.
CHECK(!decompr_zlib.read(d_state, buffer, 1));
- decompr_zlib.free(d_state);
+ // Error state is remembered.
+ CHECK(!decompr_zlib.free(d_state));
fclose(f);
}
CHECK(compr_zlib.write(c_state, data, sizeof(data)));
}
- compr_zlib.free(c_state);
+ CHECK(compr_zlib.free(c_state));
fclose(f);
f = fopen("data.zlib", "r");
// Nothing left to read.
CHECK(!decompr_zlib.read(d_state, buffer, 1));
- decompr_zlib.free(d_state);
+ // Error state is remembered.
+ CHECK(!decompr_zlib.free(d_state));
fclose(f);
}
CHECK(compr_zlib.write(c_state, data, sizeof(data)));
- compr_zlib.free(c_state);
+ CHECK(compr_zlib.free(c_state));
fclose(f);
f = fopen("data.zlib", "r");
CHECK(decompr_zlib.read(d_state, buffer, sizeof(buffer)));
CHECK(memcmp(buffer, data, sizeof(data)) == 0);
- // Nothing left to read.
- CHECK(!decompr_zlib.read(d_state, buffer, 1));
-
- decompr_zlib.free(d_state);
+ CHECK(decompr_zlib.free(d_state));
fclose(f);
}