Skip to content

Commit cfa9aa2

Browse files
authored
Improve the ByteBuffer interface in the next ABI version (#625)
* Improve the detailed description of ByteBuffer * Document which methods are planned to be removed * Include testMbstowcsInfiniteLoop in test when relevant * Improve APRCharsetDecoder robustness * Consistently use 'Bad character' in decode exception messages
1 parent 8ef7f6b commit cfa9aa2

15 files changed

Lines changed: 172 additions & 115 deletions

src/main/cpp/aprsocket.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ size_t APRSocket::write(ByteBuffer& buf)
131131
apr_status_t status = apr_socket_send(_priv->socket, buf.current(), &written);
132132
#endif
133133

134-
buf.position(buf.position() + written);
134+
buf.increment_position(written);
135135
totalWritten += written;
136136

137137
if (status != APR_SUCCESS)

src/main/cpp/bytearrayinputstream.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ int ByteArrayInputStream::read(ByteBuffer& dst)
6666
size_t bytesCopied = min(dst.remaining(), m_priv->buf.size() - m_priv->pos);
6767
std::memcpy(dst.current(), &m_priv->buf[m_priv->pos], bytesCopied);
6868
m_priv->pos += bytesCopied;
69-
dst.position(dst.position() + bytesCopied);
69+
dst.increment_position(bytesCopied);
7070
return (int)bytesCopied;
7171
}
7272
}

src/main/cpp/bytearrayoutputstream.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ void ByteArrayOutputStream::write(ByteBuffer& buf, Pool& /* p */ )
5959

6060
m_priv->array.resize(sz + count);
6161
memcpy(&m_priv->array[sz], buf.current(), count);
62-
buf.position(buf.limit());
62+
buf.increment_position(count);
6363
}
6464

6565
std::vector<unsigned char> ByteArrayOutputStream::toByteArray() const

src/main/cpp/bytebuffer.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <log4cxx/helpers/bytebuffer.h>
1919
#include <log4cxx/helpers/exception.h>
2020
#include <log4cxx/helpers/pool.h>
21+
#include <cstring>
2122

2223
using namespace LOG4CXX_NS;
2324
using namespace LOG4CXX_NS::helpers;
@@ -48,12 +49,21 @@ void ByteBuffer::clear()
4849
m_priv->pos = 0;
4950
}
5051

52+
void ByteBuffer::carry()
53+
{
54+
auto available = remaining();
55+
memmove(m_priv->base, current(), available);
56+
m_priv->lim = m_priv->cap;
57+
m_priv->pos = available;
58+
}
59+
5160
void ByteBuffer::flip()
5261
{
5362
m_priv->lim = m_priv->pos;
5463
m_priv->pos = 0;
5564
}
5665

66+
#if LOG4CXX_ABI_VERSION <= 15
5767
void ByteBuffer::position(size_t newPosition)
5868
{
5969
if (newPosition < m_priv->lim)
@@ -80,7 +90,7 @@ void ByteBuffer::limit(size_t newLimit)
8090
m_priv->pos = m_priv->lim;
8191
}
8292
}
83-
93+
#endif
8494

8595
bool ByteBuffer::put(char byte)
8696
{
@@ -128,3 +138,9 @@ size_t ByteBuffer::remaining() const
128138
return m_priv->lim - m_priv->pos;
129139
}
130140

141+
size_t ByteBuffer::increment_position(size_t byteCount)
142+
{
143+
auto available = remaining();
144+
m_priv->pos += byteCount < available ? byteCount : available;
145+
return remaining();
146+
}

src/main/cpp/charsetdecoder.cpp

Lines changed: 63 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -111,18 +111,22 @@ class APRCharsetDecoder : public CharsetDecoder
111111
{
112112
size_t inbytes_left = in.remaining();
113113
size_t initial_inbytes_left = inbytes_left;
114-
size_t pos = in.position();
115114
apr_size_t outbytes_left = initial_outbytes_left;
116115
{
117116
std::lock_guard<std::mutex> lock(mutex);
118117
stat = apr_xlate_conv_buffer((apr_xlate_t*) convset,
119-
in.data() + pos,
118+
in.current(),
120119
&inbytes_left,
121120
(char*) buf,
122121
&outbytes_left);
123122
}
124123
out.append(buf, (initial_outbytes_left - outbytes_left) / sizeof(logchar));
125-
in.position(pos + (initial_inbytes_left - inbytes_left));
124+
if (inbytes_left == initial_inbytes_left && stat == APR_SUCCESS)
125+
{
126+
stat = APR_BADCH;
127+
break;
128+
}
129+
in.increment_position(initial_inbytes_left - inbytes_left);
126130
}
127131
}
128132

@@ -181,7 +185,7 @@ class MbstowcsCharsetDecoder : public CharsetDecoder
181185
if (*src == 0)
182186
{
183187
out.append(1, (logchar) 0);
184-
in.position(in.position() + 1);
188+
in.increment_position(1);
185189
}
186190
else
187191
{
@@ -194,7 +198,7 @@ class MbstowcsCharsetDecoder : public CharsetDecoder
194198
BUFSIZE - 1,
195199
&mbstate);
196200
auto converted = src - cbuf;
197-
in.position(in.position() + converted);
201+
in.increment_position(converted);
198202

199203
if (wCharCount == (size_t) -1) // Illegal byte sequence?
200204
{
@@ -260,10 +264,10 @@ class TrivialCharsetDecoder : public CharsetDecoder
260264

261265
if ( remaining > 0)
262266
{
263-
const logchar* src = (const logchar*) (in.data() + in.position());
264-
size_t count = remaining / sizeof(logchar);
265-
out.append(src, count);
266-
in.position(in.position() + remaining);
267+
auto src = in.current();
268+
auto count = remaining / sizeof(logchar);
269+
out.append(reinterpret_cast<const logchar*>(src), count);
270+
in.increment_position(remaining);
267271
}
268272

269273
return APR_SUCCESS;
@@ -299,30 +303,29 @@ class UTF8CharsetDecoder : public CharsetDecoder
299303
virtual log4cxx_status_t decode(ByteBuffer& in,
300304
LogString& out)
301305
{
302-
if (in.remaining() > 0)
306+
auto availableByteCount = in.remaining();
307+
std::string tmp(in.current(), availableByteCount);
308+
std::string::const_iterator nextCodePoint = tmp.begin();
309+
310+
while (nextCodePoint != tmp.end())
303311
{
304-
std::string tmp(in.current(), in.remaining());
305-
std::string::const_iterator iter = tmp.begin();
312+
auto lastCodePoint = nextCodePoint;
313+
auto sv = Transcoder::decode(tmp, nextCodePoint);
306314

307-
while (iter != tmp.end())
315+
if (sv == 0xFFFF || nextCodePoint == lastCodePoint)
308316
{
309-
unsigned int sv = Transcoder::decode(tmp, iter);
310-
311-
if (sv == 0xFFFF)
312-
{
313-
size_t offset = iter - tmp.begin();
314-
in.position(in.position() + offset);
315-
return APR_BADARG;
316-
}
317-
else
318-
{
319-
Transcoder::encode(sv, out);
320-
}
317+
size_t offset = nextCodePoint - tmp.begin();
318+
in.increment_position(offset);
319+
return APR_BADCH;
320+
}
321+
else
322+
{
323+
Transcoder::encode(sv, out);
321324
}
322-
323-
in.position(in.limit());
324325
}
325326

327+
in.increment_position(availableByteCount);
328+
326329
return APR_SUCCESS;
327330
}
328331

@@ -351,20 +354,16 @@ class ISOLatinCharsetDecoder : public CharsetDecoder
351354
virtual log4cxx_status_t decode(ByteBuffer& in,
352355
LogString& out)
353356
{
354-
if (in.remaining() > 0)
355-
{
356-
357-
const unsigned char* src = (unsigned char*) in.current();
358-
const unsigned char* srcEnd = src + in.remaining();
357+
auto availableByteCount = in.remaining();
358+
auto src = in.current();
359+
auto srcEnd = src + availableByteCount;
359360

360-
while (src < srcEnd)
361-
{
362-
unsigned int sv = *(src++);
363-
Transcoder::encode(sv, out);
364-
}
365-
366-
in.position(in.limit());
361+
while (src < srcEnd)
362+
{
363+
auto sv = static_cast<unsigned int>(*src++);
364+
Transcoder::encode(sv, out);
367365
}
366+
in.increment_position(availableByteCount);
368367

369368
return APR_SUCCESS;
370369
}
@@ -399,30 +398,26 @@ class USASCIICharsetDecoder : public CharsetDecoder
399398
{
400399
log4cxx_status_t stat = APR_SUCCESS;
401400

402-
if (in.remaining() > 0)
401+
auto availableByteCount = in.remaining();
402+
auto src = in.current();
403+
auto srcEnd = src + availableByteCount;
404+
size_t byteCount = 0;
405+
while (src < srcEnd)
403406
{
407+
auto sv = static_cast<unsigned int>(*src++);
404408

405-
const unsigned char* src = (unsigned char*) in.current();
406-
const unsigned char* srcEnd = src + in.remaining();
407-
408-
while (src < srcEnd)
409+
if (sv < 0x80)
409410
{
410-
unsigned char sv = *src;
411-
412-
if (sv < 0x80)
413-
{
414-
src++;
415-
Transcoder::encode(sv, out);
416-
}
417-
else
418-
{
419-
stat = APR_BADARG;
420-
break;
421-
}
411+
++byteCount;
412+
Transcoder::encode(sv, out);
413+
}
414+
else
415+
{
416+
stat = APR_BADCH;
417+
break;
422418
}
423-
424-
in.position(src - (const unsigned char*) in.data());
425419
}
420+
in.increment_position(byteCount);
426421

427422
return stat;
428423
}
@@ -446,44 +441,43 @@ class LocaleCharsetDecoder : public CharsetDecoder
446441
log4cxx_status_t decode(ByteBuffer& in, LogString& out) override
447442
{
448443
log4cxx_status_t result = APR_SUCCESS;
449-
const char* p = in.current();
450-
size_t i = in.position();
451-
size_t remain = in.limit() - i;
444+
auto p = in.current();
445+
auto availableByteCount = in.remaining();
446+
size_t byteCount = 0;
452447
#if !LOG4CXX_CHARSET_EBCDIC
453448
if (std::mbsinit(&this->state)) // ByteBuffer not partially decoded?
454449
{
455450
// Copy single byte characters
456-
for (; 0 < remain && ((unsigned int) *p) < 0x80; --remain, ++i, p++)
451+
for (; byteCount < availableByteCount && static_cast<unsigned int>(*p) < 0x80; ++byteCount, ++p)
457452
{
458453
out.append(1, *p);
459454
}
460455
}
461456
#endif
462457
// Decode characters that may be represented by multiple bytes
463-
while (0 < remain)
458+
while (byteCount < availableByteCount)
464459
{
465460
wchar_t ch = 0;
466-
size_t n = std::mbrtowc(&ch, p, remain, &this->state);
461+
size_t n = std::mbrtowc(&ch, p, availableByteCount - byteCount, &this->state);
467462
if (0 == n) // NULL encountered?
468463
{
469-
++i;
464+
++byteCount;
470465
break;
471466
}
472467
if (static_cast<std::size_t>(-1) == n) // decoding error?
473468
{
474-
result = APR_BADARG;
469+
result = APR_BADCH;
475470
break;
476471
}
477472
if (static_cast<std::size_t>(-2) == n) // incomplete sequence?
478473
{
479474
break;
480475
}
481476
Transcoder::encode(static_cast<unsigned int>(ch), out);
482-
remain -= n;
483-
i += n;
477+
byteCount += n;
484478
p += n;
485479
}
486-
in.position(i);
480+
in.increment_position(byteCount);
487481
return result;
488482
}
489483

0 commit comments

Comments
 (0)