Coverage Report

Created: 2025-08-28 06:33

/src/freeimage-svn/FreeImage/trunk/Source/FreeImage/ZLibInterface.cpp
Line
Count
Source (jump to first uncovered line)
1
// ==========================================================
2
// ZLib library interface
3
//
4
// Design and implementation by
5
// - Floris van den Berg (flvdberg@wxs.nl)
6
//
7
// This file is part of FreeImage 3
8
//
9
// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
10
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
11
// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
12
// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
13
// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
14
// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
15
// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
16
// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
17
// THIS DISCLAIMER.
18
//
19
// Use at your own risk!
20
// ==========================================================
21
22
#include "../ZLib/zlib.h"
23
#include "FreeImage.h"
24
#include "Utilities.h"
25
#include "../ZLib/zutil.h"  /* must be the last header because of error C3163 in VS2008 (_vsnprintf defined in stdio.h) */
26
27
/**
28
Compresses a source buffer into a target buffer, using the ZLib library. 
29
Upon entry, target_size is the total size of the destination buffer, 
30
which must be at least 0.1% larger than source_size plus 12 bytes. 
31
32
@param target Destination buffer
33
@param target_size Size of the destination buffer, in bytes
34
@param source Source buffer
35
@param source_size Size of the source buffer, in bytes
36
@return Returns the actual size of the compressed buffer, returns 0 if an error occured
37
@see FreeImage_ZLibUncompress
38
*/
39
DWORD DLL_CALLCONV 
40
0
FreeImage_ZLibCompress(BYTE *target, DWORD target_size, BYTE *source, DWORD source_size) {
41
0
  uLongf dest_len = (uLongf)target_size;
42
43
0
  int zerr = compress(target, &dest_len, source, source_size);
44
0
  switch(zerr) {
45
0
    case Z_MEM_ERROR: // not enough memory
46
0
    case Z_BUF_ERROR: // not enough room in the output buffer
47
0
      FreeImage_OutputMessageProc(FIF_UNKNOWN, "Zlib error : %s", zError(zerr));
48
0
      return 0;
49
0
    case Z_OK:
50
0
      return dest_len;
51
0
  }
52
53
0
  return 0;
54
0
}
55
56
/**
57
Decompresses a source buffer into a target buffer, using the ZLib library. 
58
Upon entry, target_size is the total size of the destination buffer, 
59
which must be large enough to hold the entire uncompressed data. 
60
The size of the uncompressed data must have been saved previously by the compressor 
61
and transmitted to the decompressor by some mechanism outside the scope of this 
62
compression library.
63
64
@param target Destination buffer
65
@param target_size Size of the destination buffer, in bytes
66
@param source Source buffer
67
@param source_size Size of the source buffer, in bytes
68
@return Returns the actual size of the uncompressed buffer, returns 0 if an error occured
69
@see FreeImage_ZLibCompress
70
*/
71
DWORD DLL_CALLCONV 
72
0
FreeImage_ZLibUncompress(BYTE *target, DWORD target_size, BYTE *source, DWORD source_size) {
73
0
  uLongf dest_len = (uLongf)target_size;
74
75
0
  int zerr = uncompress(target, &dest_len, source, source_size);
76
0
  switch(zerr) {
77
0
    case Z_MEM_ERROR: // not enough memory
78
0
    case Z_BUF_ERROR: // not enough room in the output buffer
79
0
    case Z_DATA_ERROR: // input data was corrupted
80
0
      FreeImage_OutputMessageProc(FIF_UNKNOWN, "Zlib error : %s", zError(zerr));
81
0
      return 0;
82
0
    case Z_OK:
83
0
      return dest_len;
84
0
  }
85
86
0
  return 0;
87
0
}
88
89
/**
90
Compresses a source buffer into a target buffer, using the ZLib library. 
91
On success, the target buffer contains a GZIP compatible layout.
92
Upon entry, target_size is the total size of the destination buffer, 
93
which must be at least 0.1% larger than source_size plus 24 bytes. 
94
95
@param target Destination buffer
96
@param target_size Size of the destination buffer, in bytes
97
@param source Source buffer
98
@param source_size Size of the source buffer, in bytes
99
@return Returns the actual size of the compressed buffer, returns 0 if an error occured
100
@see FreeImage_ZLibCompress
101
*/
102
DWORD DLL_CALLCONV 
103
0
FreeImage_ZLibGZip(BYTE *target, DWORD target_size, BYTE *source, DWORD source_size) {
104
0
  uLongf dest_len = (uLongf)target_size - 12;
105
0
  DWORD crc = crc32(0L, NULL, 0);
106
107
    // set up header (stolen from zlib/gzio.c)
108
0
    sprintf((char *)target, "%c%c%c%c%c%c%c%c", 0x1f, 0x8b,
109
0
         Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/);
110
0
    int zerr = compress2(target + 8, &dest_len, source, source_size, Z_BEST_COMPRESSION);
111
0
  switch(zerr) {
112
0
    case Z_MEM_ERROR: // not enough memory
113
0
    case Z_BUF_ERROR: // not enough room in the output buffer
114
0
      FreeImage_OutputMessageProc(FIF_UNKNOWN, "Zlib error : %s", zError(zerr));
115
0
      return 0;
116
0
        case Z_OK: {
117
            // patch header, setup crc and length (stolen from mod_trace_output)
118
0
            BYTE *p = target + 8; *p++ = 2; *p = OS_CODE; // xflags, os_code
119
0
          crc = crc32(crc, source, source_size);
120
0
          memcpy(target + 4 + dest_len, &crc, 4);
121
0
          memcpy(target + 8 + dest_len, &source_size, 4);
122
0
            return dest_len + 12;
123
0
        }
124
0
  }
125
0
  return 0;
126
0
}
127
128
/**
129
Decompresses a gzipped source buffer into a target buffer, using the ZLib library. 
130
Upon entry, target_size is the total size of the destination buffer, 
131
which must be large enough to hold the entire uncompressed data. 
132
The size of the uncompressed data must have been saved previously by the compressor 
133
and transmitted to the decompressor by some mechanism outside the scope of this 
134
compression library.
135
136
@param target Destination buffer
137
@param target_size Size of the destination buffer, in bytes
138
@param source Source buffer
139
@param source_size Size of the source buffer, in bytes
140
@return Returns the actual size of the uncompressed buffer, returns 0 if an error occured
141
@see FreeImage_ZLibGZip
142
*/
143
144
0
static int get_byte(z_stream *stream) {
145
0
    if (stream->avail_in <= 0) return EOF;
146
0
    stream->avail_in--;
147
0
    return *(stream->next_in)++;
148
0
}
149
150
0
static int checkheader(z_stream *stream) {
151
0
    int flags, c;
152
0
    DWORD len;
153
154
0
    if (get_byte(stream) != 0x1f || get_byte(stream) != 0x8b)
155
0
        return Z_DATA_ERROR;
156
0
    if (get_byte(stream) != Z_DEFLATED || ((flags = get_byte(stream)) & 0xE0) != 0)
157
0
        return Z_DATA_ERROR;
158
0
    for (len = 0; len < 6; len++) (void)get_byte(stream);
159
160
0
    if ((flags & 0x04) != 0) { /* skip the extra field */
161
0
        len  =  (DWORD)get_byte(stream);
162
0
        len += ((DWORD)get_byte(stream)) << 8;
163
        /* len is garbage if EOF but the loop below will quit anyway */
164
0
        while (len-- != 0 && get_byte(stream) != EOF) ;
165
0
    }
166
0
    if ((flags & 0x08) != 0) { /* skip the original file name */
167
0
        while ((c = get_byte(stream)) != 0 && c != EOF) ;
168
0
    }
169
0
    if ((flags & 0x10) != 0) {   /* skip the .gz file comment */
170
0
        while ((c = get_byte(stream)) != 0 && c != EOF) ;
171
0
    }
172
0
    if ((flags & 0x02) != 0) {  /* skip the header crc */
173
0
        for (len = 0; len < 2; len++) (void)get_byte(stream);
174
0
    }
175
0
    return Z_OK;
176
0
}
177
178
DWORD DLL_CALLCONV 
179
0
FreeImage_ZLibGUnzip(BYTE *target, DWORD target_size, BYTE *source, DWORD source_size) {
180
0
    DWORD src_len  = source_size;
181
0
    DWORD dest_len = target_size;
182
0
    int   zerr     = Z_DATA_ERROR;
183
184
0
    if (src_len > 0) {
185
0
        z_stream stream;
186
0
        memset(&stream, 0, sizeof (stream));
187
0
        if ((zerr = inflateInit2(&stream, -MAX_WBITS)) == Z_OK) {
188
0
            stream.next_in  = source;
189
0
            stream.avail_in = source_size;
190
191
0
            stream.next_out  = target;
192
0
            stream.avail_out = target_size;
193
194
0
            if ((zerr = checkheader(&stream)) == Z_OK) {
195
0
                zerr = inflate (&stream, Z_NO_FLUSH);
196
0
                dest_len = target_size - stream.avail_out;
197
198
0
                if (zerr == Z_OK || zerr == Z_STREAM_END)
199
0
                    inflateEnd(&stream);
200
0
            } 
201
0
        }
202
0
    }
203
0
    if (zerr != Z_OK && zerr != Z_STREAM_END) {
204
0
        FreeImage_OutputMessageProc(FIF_UNKNOWN, "Zlib error : %s", zError(zerr));
205
0
        return 0;
206
0
    }
207
0
    return dest_len;
208
0
}
209
210
/**
211
Update a running crc from source and return the updated crc, using the ZLib library.
212
If source is NULL, this function returns the required initial value for the crc.
213
214
@param crc Running crc value
215
@param source Source buffer
216
@param source_size Size of the source buffer, in bytes
217
@return Returns the new crc value
218
*/
219
DWORD DLL_CALLCONV 
220
0
FreeImage_ZLibCRC32(DWORD crc, BYTE *source, DWORD source_size) {
221
222
0
    return crc32(crc, source, source_size);
223
0
}