if (!in_stream.check(2, wait))
return false;
- const U8* iptr = in_stream.getptr();
- const U8* eptr = in_stream.getend();
- size_t length = min((eptr - iptr)/2, maxSize);
+ size_t length = min(in_stream.avail()/2, maxSize);
+ const U8* iptr = in_stream.getptr(length*2);
U8* optr = (U8*) end;
for (size_t i=0; i<length; i++) {
optr[i] = v;
}
- in_stream.setptr(iptr + length*2);
+ in_stream.setptr(length*2);
end += length;
return true;
HexOutStream::writeBuffer() {
U8* pos = start;
while (pos != ptr) {
- out_stream.check(2);
- U8* optr = out_stream.getptr();
- U8* oend = out_stream.getend();
- size_t length = min(ptr-pos, (oend-optr)/2);
+ U8* optr = out_stream.getptr(2);
+ size_t length = min(ptr-pos, out_stream.avail()/2);
for (size_t i=0; i<length; i++) {
optr[i*2] = intToHex((pos[i] >> 4) & 0xf);
optr[i*2+1] = intToHex(pos[i] & 0xf);
}
- out_stream.setptr(optr + length*2);
+ out_stream.setptr(length*2);
pos += length;
}
offset += ptr - start;
#define __RDR_INSTREAM_H__
#include <rdr/types.h>
+#include <rdr/Exception.h>
#include <string.h> // for memcpy
namespace rdr {
virtual size_t pos() = 0;
- // getptr(), getend() and setptr() are "dirty" methods which allow you to
- // manipulate the buffer directly. This is useful for a stream which is a
- // wrapper around an underlying stream.
+ // getptr() and setptr() are "dirty" methods which allow you direct access
+ // to the buffer. This is useful for a stream which is a wrapper around an
+ // some other stream API.
- inline const U8* getptr() const { return ptr; }
- inline const U8* getend() const { return end; }
- inline void setptr(const U8* p) { ptr = p; }
+ inline const U8* getptr(size_t length) { check(length); return ptr; }
+ inline void setptr(size_t length) { if (length > avail())
+ throw Exception("Input stream overflow");
+ skip(length); }
private:
#define __RDR_OUTSTREAM_H__
#include <rdr/types.h>
+#include <rdr/Exception.h>
#include <rdr/InStream.h>
#include <string.h> // for memcpy
virtual void cork(bool enable) { corked = enable; flush(); }
- // getptr(), getend() and setptr() are "dirty" methods which allow you to
- // manipulate the buffer directly. This is useful for a stream which is a
- // wrapper around an underlying stream.
+ // getptr() and setptr() are "dirty" methods which allow you direct access
+ // to the buffer. This is useful for a stream which is a wrapper around an
+ // some other stream API. Note that setptr() should not called with a value
+ // larger than the bytes actually written as doing so can result in
+ // security issues. Use pad() in such cases instead.
- inline U8* getptr() { return ptr; }
- inline U8* getend() { return end; }
- inline void setptr(U8* p) { ptr = p; }
+ inline U8* getptr(size_t length) { check(length); return ptr; }
+ inline void setptr(size_t length) { if (length > avail())
+ throw Exception("Output stream overflow");
+ ptr += length; }
private:
size_t n = underlying->check(1, wait);
if (n == 0) return false;
- zs->next_in = (U8*)underlying->getptr();
- zs->avail_in = underlying->avail();
- if (zs->avail_in > bytesIn)
- zs->avail_in = bytesIn;
+ size_t length = underlying->avail();
+ if (length > bytesIn)
+ length = bytesIn;
+ zs->next_in = (U8*)underlying->getptr(length);
+ zs->avail_in = length;
int rc = inflate(zs, Z_SYNC_FLUSH);
if (rc < 0) {
throw Exception("ZlibInStream: inflate failed");
}
- bytesIn -= zs->next_in - underlying->getptr();
+ bytesIn -= length - zs->avail_in;
end = zs->next_out;
- underlying->setptr(zs->next_in);
+ underlying->setptr(length - zs->avail_in);
return true;
}
return;
do {
- underlying->check(1);
- zs->next_out = underlying->getptr();
- zs->avail_out = underlying->avail();
+ size_t chunk;
+ zs->next_out = underlying->getptr(1);
+ zs->avail_out = chunk = underlying->avail();
#ifdef ZLIBOUT_DEBUG
vlog.debug("calling deflate, avail_in %d, avail_out %d",
zs->next_out-underlying->getptr());
#endif
- underlying->setptr(zs->next_out);
+ underlying->setptr(chunk - zs->avail_out);
} while (zs->avail_out == 0);
}
struct JPEG_DEST_MGR {
struct jpeg_destination_mgr pub;
JpegCompressor *instance;
+ size_t chunkSize;
};
static void
JpegCompressor *jc = dest->instance;
jc->clear();
- dest->pub.next_output_byte = jc->getptr();
- dest->pub.free_in_buffer = jc->avail();
+ dest->pub.next_output_byte = jc->getptr(jc->length());
+ dest->pub.free_in_buffer = dest->chunkSize = jc->avail();
}
static boolean
JPEG_DEST_MGR *dest = (JPEG_DEST_MGR *)cinfo->dest;
JpegCompressor *jc = dest->instance;
- jc->setptr(jc->getend());
- jc->check(jc->length());
- dest->pub.next_output_byte = jc->getptr();
- dest->pub.free_in_buffer = jc->avail();
+ jc->setptr(jc->avail());
+ dest->pub.next_output_byte = jc->getptr(jc->length());
+ dest->pub.free_in_buffer = dest->chunkSize = jc->avail();
return TRUE;
}
JPEG_DEST_MGR *dest = (JPEG_DEST_MGR *)cinfo->dest;
JpegCompressor *jc = dest->instance;
- jc->setptr(dest->pub.next_output_byte);
+ jc->setptr(dest->chunkSize - dest->pub.free_in_buffer);
}
JpegCompressor::JpegCompressor(int bufferLen) : MemOutStream(bufferLen)