Skip to content

Commit 13ae8dc

Browse files
committed
C API: fix several bugs and improve code in several places
1 parent 3c9c334 commit 13ae8dc

File tree

4 files changed

+87
-88
lines changed

4 files changed

+87
-88
lines changed

src/api/Compressor.cpp

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,11 @@ namespace kanzi {
7373
virtual streamsize xsputn(const char* s, streamsize sz) {
7474
return WRITE(_fd, s, sz);
7575
}
76+
77+
int sync() {
78+
// No internal buffer — nothing to flush. Indicate success
79+
return 0;
80+
}
7681
};
7782

7883
class FileOutputStream FINAL : public ostream
@@ -105,19 +110,13 @@ int CDECL initCompressor(struct cData* pData, FILE* dst, struct cContext** pCtx)
105110
return Error::ERR_CREATE_COMPRESSOR;
106111

107112
string transform = TransformFactory<byte>::getName(TransformFactory<byte>::getType(pData->transform));
108-
109-
if (transform.length() >= 63)
110-
return Error::ERR_INVALID_PARAM;
111-
112-
strncpy(pData->transform, transform.data(), transform.length());
113-
pData->transform[transform.length() + 1] = 0;
114113
string entropy = EntropyEncoderFactory::getName(EntropyEncoderFactory::getType(pData->entropy));
115114

116-
if (entropy.length() >= 15)
115+
if ((transform.length() >= 63) || (entropy.length() >= 15))
117116
return Error::ERR_INVALID_PARAM;
118117

119-
strncpy(pData->entropy, entropy.data(), entropy.length());
120-
pData->entropy[entropy.length() + 1] = 0;
118+
snprintf(pData->transform, sizeof(pData->transform), "%s", transform.c_str());
119+
snprintf(pData->entropy, sizeof(pData->entropy), "%s", entropy.c_str());
121120
pData->blockSize = (pData->blockSize + 15) & -16;
122121

123122
*pCtx = nullptr;
@@ -145,7 +144,7 @@ int CDECL initCompressor(struct cData* pData, FILE* dst, struct cContext** pCtx)
145144
cctx->fos = fos;
146145
*pCtx = cctx;
147146
}
148-
catch (exception&) {
147+
catch (const exception& e) {
149148
if (fos != nullptr)
150149
delete fos;
151150

@@ -158,29 +157,30 @@ int CDECL initCompressor(struct cData* pData, FILE* dst, struct cContext** pCtx)
158157
return 0;
159158
}
160159

161-
int CDECL compress(struct cContext* pCtx, const BYTE* src, int* inSize, int* outSize)
160+
int CDECL compress(struct cContext* pCtx, const unsigned char* src, int* inSize, int* outSize)
162161
{
163-
*outSize = 0;
164-
int res = 0;
165-
166-
if ((pCtx == nullptr) || (*inSize > int(pCtx->blockSize))) {
162+
if ((pCtx == nullptr) || (inSize == nullptr) || (outSize == nullptr) || (*inSize > int(pCtx->blockSize))) {
167163
*inSize = 0;
168164
return Error::ERR_INVALID_PARAM;
169165
}
170166

171-
CompressedOutputStream* pCos = (CompressedOutputStream*)pCtx->pCos;
172-
*inSize = 0;
167+
*outSize = 0;
168+
int res = 0;
169+
CompressedOutputStream* pCos = static_cast<CompressedOutputStream*>(pCtx->pCos);
173170

174-
if (pCos == nullptr)
171+
if (pCos == nullptr) {
172+
*outSize = 0;
175173
return Error::ERR_INVALID_PARAM;
174+
}
176175

177176
try {
178177
const uint64 w = pCos->getWritten();
179178
pCos->write((const char*)src, streamsize(*inSize));
180179
res = pCos->good() ? 0 : Error::ERR_WRITE_FILE;
181180
*outSize = int(pCos->getWritten() - w);
182181
}
183-
catch (exception&) {
182+
catch (const exception&) {
183+
*outSize = 0;
184184
return Error::ERR_UNKNOWN;
185185
}
186186

@@ -204,7 +204,7 @@ int CDECL disposeCompressor(struct cContext* pCtx, int* outSize)
204204
*outSize = int(pCos->getWritten() - w);
205205
}
206206
}
207-
catch (exception&) {
207+
catch (const exception&) {
208208
return Error::ERR_UNKNOWN;
209209
}
210210

@@ -218,7 +218,7 @@ int CDECL disposeCompressor(struct cContext* pCtx, int* outSize)
218218
pCtx->fos = nullptr;
219219
delete pCtx;
220220
}
221-
catch (exception&) {
221+
catch (const exception&) {
222222
if (pCtx->fos != nullptr)
223223
delete (FileOutputStream*)pCtx->fos;
224224

src/api/Compressor.hpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,13 @@ limitations under the License.
2424
#endif
2525

2626
#include <stdio.h>
27+
#include <stdint.h>
2728

2829

2930
#ifdef __cplusplus
3031
extern "C" {
3132
#endif
3233

33-
typedef unsigned char BYTE;
34-
3534
/**
3635
* Compression parameters
3736
*/
@@ -58,7 +57,7 @@ limitations under the License.
5857
/**
5958
* Initialize the compressor internal states.
6059
*
61-
* @param cParam [IN] - the compression parameters
60+
* @param cParam [IN|OUT] - the compression parameters, transform and enropy are validated and rewritten
6261
* @param dst [IN] - the destination stream of compressed data
6362
* @param ctx [IN|OUT] - pointer to the compression context created by the call
6463
*
@@ -77,7 +76,7 @@ limitations under the License.
7776
*
7877
* @return 0 in case of success
7978
*/
80-
int CDECL compress(struct cContext* ctx, const BYTE* src, int* inSize, int* outSize);
79+
int CDECL compress(struct cContext* ctx, const unsigned char* src, int* inSize, int* outSize);
8180

8281
/**
8382
* Dispose the compressor and cleanup memory resources.

src/api/Decompressor.cpp

Lines changed: 60 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -49,31 +49,36 @@ namespace kanzi {
4949
char _buffer[BUF_SIZE];
5050

5151
virtual int_type underflow() {
52-
if (gptr() < egptr())
53-
return traits_type::to_int_type(*gptr());
54-
55-
const int pbSz = min(int(gptr() - eback()), BUF_SIZE - 4);
56-
memmove(&_buffer[BUF_SIZE - pbSz], gptr() - pbSz, pbSz);
57-
const int r = int(READ(_fd, &_buffer[4], BUF_SIZE - 4));
58-
59-
if (r <= 0)
60-
return EOF;
61-
62-
setg(&_buffer[4 - pbSz], &_buffer[4], &_buffer[4 + r]);
63-
return traits_type::to_int_type(*gptr());
64-
}
65-
};
66-
67-
class FileInputStream FINAL : public istream
68-
{
69-
private:
70-
ifstreambuf _buf;
71-
72-
public:
73-
FileInputStream(int fd) : istream(nullptr), _buf(fd) {
74-
rdbuf(&_buf);
75-
}
76-
};
52+
if (gptr() < egptr())
53+
return traits_type::to_int_type(*gptr());
54+
55+
// Preserve up to 4 bytes of putback
56+
const int putback = std::min<int>(gptr() - eback(), 4);
57+
58+
// Move putback bytes to the front
59+
std::memmove(_buffer + (4 - putback), gptr() - putback, putback);
60+
61+
// Read new bytes after putback
62+
const int n = READ(_fd, _buffer + 4, BUF_SIZE - 4);
63+
if (n <= 0)
64+
return traits_type::eof();
65+
66+
// Set new buffer pointers
67+
setg(_buffer + (4 - putback), _buffer + 4, _buffer + 4 + n);
68+
return traits_type::to_int_type(*gptr());
69+
}
70+
};
71+
72+
class FileInputStream FINAL : public istream
73+
{
74+
private:
75+
ifstreambuf _buf;
76+
77+
public:
78+
FileInputStream(int fd) : istream(nullptr), _buf(fd) {
79+
rdbuf(&_buf);
80+
}
81+
};
7782
}
7883

7984

@@ -103,25 +108,16 @@ int CDECL initDecompressor(struct dData* pData, FILE* src, struct dContext** pCt
103108
if (pData->headerless != 0) {
104109
// Headerless mode: process params
105110
string transform = TransformFactory<byte>::getName(TransformFactory<byte>::getType(pData->transform));
106-
107-
if (transform.length() >= 63) {
108-
delete fis;
109-
delete dctx;
110-
return Error::ERR_INVALID_PARAM;
111-
}
112-
113-
strncpy(pData->transform, transform.data(), transform.length());
114-
pData->transform[transform.length() + 1] = 0;
115111
string entropy = EntropyEncoderFactory::getName(EntropyEncoderFactory::getType(pData->entropy));
116112

117-
if (entropy.length() >= 15) {
113+
if ((transform.length() >= 63) || (entropy.length() >= 15)) {
118114
delete fis;
119115
delete dctx;
120116
return Error::ERR_INVALID_PARAM;
121117
}
122118

123-
strncpy(pData->entropy, entropy.data(), entropy.length());
124-
pData->entropy[entropy.length() + 1] = 0;
119+
strncpy(pData->transform, transform.c_str(), 63);
120+
strncpy(pData->entropy, entropy.c_str(), 15);
125121
pData->blockSize = (pData->blockSize + 15) & -16;
126122

127123
dctx->pCis = new CompressedInputStream(*fis, pData->jobs,
@@ -141,7 +137,7 @@ int CDECL initDecompressor(struct dData* pData, FILE* src, struct dContext** pCt
141137
dctx->fis = fis;
142138
*pCtx = dctx;
143139
}
144-
catch (exception&) {
140+
catch (const exception&) {
145141
if (fis != nullptr)
146142
delete fis;
147143

@@ -154,30 +150,38 @@ int CDECL initDecompressor(struct dData* pData, FILE* src, struct dContext** pCt
154150
return 0;
155151
}
156152

157-
int CDECL decompress(struct dContext* pCtx, BYTE* dst, int* inSize, int* outSize)
153+
int CDECL decompress(struct dContext* pCtx, unsigned char* dst, int* inSize, int* outSize)
158154
{
159-
*inSize = 0;
160-
int res = 0;
161-
162-
if ((pCtx == nullptr) || (*outSize > int(pCtx->bufferSize))) {
155+
if ((pCtx == nullptr) || (inSize == nullptr) || (outSize == nullptr) ||
156+
(*outSize < 0) || (*outSize > int(pCtx->bufferSize))) {
163157
*outSize = 0;
164158
return Error::ERR_INVALID_PARAM;
165159
}
166160

167-
CompressedInputStream* pCis = (CompressedInputStream*)pCtx->pCis;
168-
*outSize = 0;
161+
if (*outSize == 0)
162+
return 0;
163+
164+
*inSize = 0;
165+
int res = 0;
166+
CompressedInputStream* pCis = static_cast<CompressedInputStream*>(pCtx->pCis);
169167

170-
if (pCis == nullptr)
168+
if (pCis == nullptr) {
169+
*outSize = 0;
171170
return Error::ERR_INVALID_PARAM;
171+
}
172172

173173
try {
174-
const uint64 r = int(pCis->getRead());
174+
const uint64 r = pCis->getRead();
175175
pCis->read((char*)dst, streamsize(*outSize));
176-
res = pCis->good() ? 0 : Error::ERR_READ_FILE;
176+
177+
if (!pCis->good() && !pCis->eof())
178+
return Error::ERR_READ_FILE;
179+
177180
*inSize = int(pCis->getRead() - r);
178181
*outSize = int(pCis->gcount());
179182
}
180-
catch (exception&) {
183+
catch (const exception&) {
184+
*outSize = 0;
181185
return Error::ERR_UNKNOWN;
182186
}
183187

@@ -190,28 +194,25 @@ int CDECL disposeDecompressor(struct dContext* pCtx)
190194
if (pCtx == nullptr)
191195
return Error::ERR_INVALID_PARAM;
192196

193-
CompressedInputStream* pCis = (CompressedInputStream*)pCtx->pCis;
197+
CompressedInputStream* pCis = static_cast<CompressedInputStream*>(pCtx->pCis);
194198

195199
try {
196200
if (pCis != nullptr) {
197201
pCis->close();
198-
}
199-
}
200-
catch (exception&) {
201-
return Error::ERR_UNKNOWN;
202-
}
203-
204-
try {
205-
if (pCis != nullptr)
206202
delete pCis;
203+
pCis = nullptr;
204+
}
207205

208206
if (pCtx->fis != nullptr)
209207
delete (FileInputStream*)pCtx->fis;
210208

211209
pCtx->fis = nullptr;
212210
delete pCtx;
213211
}
214-
catch (exception&) {
212+
catch (const exception&) {
213+
if (pCis != nullptr)
214+
delete pCis;
215+
215216
if (pCtx->fis != nullptr)
216217
delete (FileInputStream*)pCtx->fis;
217218

src/api/Decompressor.hpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ limitations under the License.
2929
extern "C" {
3030
#endif
3131

32-
typedef unsigned char BYTE;
33-
3432
/**
3533
* Decompression parameters
3634
*/
@@ -62,7 +60,8 @@ limitations under the License.
6260
/**
6361
* Initialize the decompressor internal states.
6462
*
65-
* @param dParam [IN] - the decompression parameters
63+
* @param dParam [IN|OUT] - the decompression parameters. Transform and entropy are
64+
validated and rewritten.
6665
* @param src [IN] - the source stream of compressed data
6766
* @param ctx [IN|OUT] - a pointer to the decompression context created by the call
6867
*
@@ -81,7 +80,7 @@ limitations under the License.
8180
*
8281
* @return 0 in case of success
8382
*/
84-
int CDECL decompress(struct dContext* ctx, BYTE* dst, int* inSize, int* outSize);
83+
int CDECL decompress(struct dContext* ctx, unsigned char* dst, int* inSize, int* outSize);
8584

8685
/**
8786
* Dispose the decompressor and cleanup memory resources.

0 commit comments

Comments
 (0)