Coverage Report

Created: 2026-07-30 07:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/logging-log4cxx/src/main/cpp/charsetdecoder.cpp
Line
Count
Source
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 * contributor license agreements.  See the NOTICE file distributed with
4
 * this work for additional information regarding copyright ownership.
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
6
 * (the "License"); you may not use this file except in compliance with
7
 * the License.  You may obtain a copy of the License at
8
 *
9
 *      http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
#define NOMINMAX /* tell windows not to define min/max macros */
18
#include <log4cxx/private/string_c11.h>
19
#include <log4cxx/logstring.h>
20
#include <log4cxx/helpers/charsetdecoder.h>
21
#include <log4cxx/helpers/bytebuffer.h>
22
#include <log4cxx/helpers/exception.h>
23
#include <log4cxx/helpers/pool.h>
24
#include <log4cxx/helpers/loglog.h>
25
#include <apr_xlate.h>
26
#if !defined(LOG4CXX)
27
  #define LOG4CXX 1
28
#endif
29
#include <log4cxx/private/log4cxx_private.h>
30
#include <locale.h>
31
#include <apr_portable.h>
32
#include <log4cxx/helpers/stringhelper.h>
33
#include <log4cxx/helpers/transcoder.h>
34
#include <mutex>
35
36
using namespace LOG4CXX_NS;
37
using namespace LOG4CXX_NS::helpers;
38
39
IMPLEMENT_LOG4CXX_OBJECT(CharsetDecoder)
40
41
42
namespace LOG4CXX_NS
43
{
44
namespace helpers
45
{
46
47
#if APR_HAS_XLATE
48
/**
49
 *  Converts from an arbitrary encoding to LogString
50
 *    using apr_xlate.  Requires real iconv implementation,
51
*    apr-iconv will crash in use.
52
 */
53
class APRCharsetDecoder : public CharsetDecoder
54
{
55
  public:
56
    /**
57
     *  Creates a new instance.
58
     *  @param frompage name of source encoding.
59
     */
60
814
    APRCharsetDecoder(const LogString& frompage) : pool()
61
814
    {
62
#if LOG4CXX_LOGCHAR_IS_WCHAR
63
      const char* topage = "WCHAR_T";
64
#endif
65
#if LOG4CXX_LOGCHAR_IS_UTF8
66
      const char* topage = "UTF-8";
67
#endif
68
#if LOG4CXX_LOGCHAR_IS_UNICHAR
69
      const char* topage = "UTF-16";
70
#endif
71
814
      std::string fpage(Transcoder::encodeCharsetName(frompage));
72
814
      apr_status_t stat = apr_xlate_open(&convset,
73
814
          topage,
74
814
          fpage.c_str(),
75
814
          pool.getAPRPool());
76
77
814
      if (stat != APR_SUCCESS)
78
0
      {
79
0
        throw IllegalArgumentException(frompage);
80
0
      }
81
814
    }
log4cxx::helpers::APRCharsetDecoder::APRCharsetDecoder(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Line
Count
Source
60
411
    APRCharsetDecoder(const LogString& frompage) : pool()
61
411
    {
62
#if LOG4CXX_LOGCHAR_IS_WCHAR
63
      const char* topage = "WCHAR_T";
64
#endif
65
411
#if LOG4CXX_LOGCHAR_IS_UTF8
66
411
      const char* topage = "UTF-8";
67
411
#endif
68
#if LOG4CXX_LOGCHAR_IS_UNICHAR
69
      const char* topage = "UTF-16";
70
#endif
71
411
      std::string fpage(Transcoder::encodeCharsetName(frompage));
72
411
      apr_status_t stat = apr_xlate_open(&convset,
73
411
          topage,
74
411
          fpage.c_str(),
75
411
          pool.getAPRPool());
76
77
411
      if (stat != APR_SUCCESS)
78
0
      {
79
0
        throw IllegalArgumentException(frompage);
80
0
      }
81
411
    }
log4cxx::helpers::APRCharsetDecoder::APRCharsetDecoder(std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > const&)
Line
Count
Source
60
403
    APRCharsetDecoder(const LogString& frompage) : pool()
61
403
    {
62
403
#if LOG4CXX_LOGCHAR_IS_WCHAR
63
403
      const char* topage = "WCHAR_T";
64
403
#endif
65
#if LOG4CXX_LOGCHAR_IS_UTF8
66
      const char* topage = "UTF-8";
67
#endif
68
#if LOG4CXX_LOGCHAR_IS_UNICHAR
69
      const char* topage = "UTF-16";
70
#endif
71
403
      std::string fpage(Transcoder::encodeCharsetName(frompage));
72
403
      apr_status_t stat = apr_xlate_open(&convset,
73
403
          topage,
74
403
          fpage.c_str(),
75
403
          pool.getAPRPool());
76
77
403
      if (stat != APR_SUCCESS)
78
0
      {
79
0
        throw IllegalArgumentException(frompage);
80
0
      }
81
403
    }
82
83
    /**
84
     *  Destructor.
85
     */
86
    virtual ~APRCharsetDecoder()
87
814
    {
88
814
    }
89
90
    virtual log4cxx_status_t decode(ByteBuffer& in,
91
      LogString& out)
92
526k
    {
93
526k
      enum { BUFSIZE = 256 };
94
526k
      logchar buf[BUFSIZE];
95
526k
      const apr_size_t initial_outbytes_left = BUFSIZE * sizeof(logchar);
96
526k
      apr_status_t stat = APR_SUCCESS;
97
98
526k
      if (in.remaining() == 0)
99
808
      {
100
808
        size_t outbytes_left = initial_outbytes_left;
101
808
        {
102
808
          std::lock_guard<std::mutex> lock(mutex);
103
808
          stat = apr_xlate_conv_buffer((apr_xlate_t*) convset,
104
808
              NULL, NULL, (char*) buf, &outbytes_left);
105
808
        }
106
808
        out.append(buf, (initial_outbytes_left - outbytes_left) / sizeof(logchar));
107
808
      }
108
525k
      else
109
525k
      {
110
1.06M
        while (in.remaining() > 0 && stat == APR_SUCCESS)
111
536k
        {
112
536k
          size_t inbytes_left = in.remaining();
113
536k
          size_t initial_inbytes_left = inbytes_left;
114
536k
          apr_size_t outbytes_left = initial_outbytes_left;
115
536k
          {
116
536k
            std::lock_guard<std::mutex> lock(mutex);
117
536k
            stat = apr_xlate_conv_buffer((apr_xlate_t*) convset,
118
536k
                in.current(),
119
536k
                &inbytes_left,
120
536k
                (char*) buf,
121
536k
                &outbytes_left);
122
536k
          }
123
536k
          out.append(buf, (initial_outbytes_left - outbytes_left) / sizeof(logchar));
124
536k
          if (inbytes_left == initial_inbytes_left && stat == APR_SUCCESS)
125
0
          {
126
0
            stat = APR_BADCH;
127
0
            break;
128
0
          }
129
536k
          in.increment_position(initial_inbytes_left - inbytes_left);
130
536k
        }
131
525k
      }
132
133
526k
      return stat;
134
526k
    }
log4cxx::helpers::APRCharsetDecoder::decode(log4cxx::helpers::ByteBuffer&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
Line
Count
Source
92
66.7k
    {
93
66.7k
      enum { BUFSIZE = 256 };
94
66.7k
      logchar buf[BUFSIZE];
95
66.7k
      const apr_size_t initial_outbytes_left = BUFSIZE * sizeof(logchar);
96
66.7k
      apr_status_t stat = APR_SUCCESS;
97
98
66.7k
      if (in.remaining() == 0)
99
408
      {
100
408
        size_t outbytes_left = initial_outbytes_left;
101
408
        {
102
408
          std::lock_guard<std::mutex> lock(mutex);
103
408
          stat = apr_xlate_conv_buffer((apr_xlate_t*) convset,
104
408
              NULL, NULL, (char*) buf, &outbytes_left);
105
408
        }
106
408
        out.append(buf, (initial_outbytes_left - outbytes_left) / sizeof(logchar));
107
408
      }
108
66.2k
      else
109
66.2k
      {
110
141k
        while (in.remaining() > 0 && stat == APR_SUCCESS)
111
75.5k
        {
112
75.5k
          size_t inbytes_left = in.remaining();
113
75.5k
          size_t initial_inbytes_left = inbytes_left;
114
75.5k
          apr_size_t outbytes_left = initial_outbytes_left;
115
75.5k
          {
116
75.5k
            std::lock_guard<std::mutex> lock(mutex);
117
75.5k
            stat = apr_xlate_conv_buffer((apr_xlate_t*) convset,
118
75.5k
                in.current(),
119
75.5k
                &inbytes_left,
120
75.5k
                (char*) buf,
121
75.5k
                &outbytes_left);
122
75.5k
          }
123
75.5k
          out.append(buf, (initial_outbytes_left - outbytes_left) / sizeof(logchar));
124
75.5k
          if (inbytes_left == initial_inbytes_left && stat == APR_SUCCESS)
125
0
          {
126
0
            stat = APR_BADCH;
127
0
            break;
128
0
          }
129
75.5k
          in.increment_position(initial_inbytes_left - inbytes_left);
130
75.5k
        }
131
66.2k
      }
132
133
66.7k
      return stat;
134
66.7k
    }
log4cxx::helpers::APRCharsetDecoder::decode(log4cxx::helpers::ByteBuffer&, std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >&)
Line
Count
Source
92
459k
    {
93
459k
      enum { BUFSIZE = 256 };
94
459k
      logchar buf[BUFSIZE];
95
459k
      const apr_size_t initial_outbytes_left = BUFSIZE * sizeof(logchar);
96
459k
      apr_status_t stat = APR_SUCCESS;
97
98
459k
      if (in.remaining() == 0)
99
400
      {
100
400
        size_t outbytes_left = initial_outbytes_left;
101
400
        {
102
400
          std::lock_guard<std::mutex> lock(mutex);
103
400
          stat = apr_xlate_conv_buffer((apr_xlate_t*) convset,
104
400
              NULL, NULL, (char*) buf, &outbytes_left);
105
400
        }
106
400
        out.append(buf, (initial_outbytes_left - outbytes_left) / sizeof(logchar));
107
400
      }
108
459k
      else
109
459k
      {
110
919k
        while (in.remaining() > 0 && stat == APR_SUCCESS)
111
460k
        {
112
460k
          size_t inbytes_left = in.remaining();
113
460k
          size_t initial_inbytes_left = inbytes_left;
114
460k
          apr_size_t outbytes_left = initial_outbytes_left;
115
460k
          {
116
460k
            std::lock_guard<std::mutex> lock(mutex);
117
460k
            stat = apr_xlate_conv_buffer((apr_xlate_t*) convset,
118
460k
                in.current(),
119
460k
                &inbytes_left,
120
460k
                (char*) buf,
121
460k
                &outbytes_left);
122
460k
          }
123
460k
          out.append(buf, (initial_outbytes_left - outbytes_left) / sizeof(logchar));
124
460k
          if (inbytes_left == initial_inbytes_left && stat == APR_SUCCESS)
125
0
          {
126
0
            stat = APR_BADCH;
127
0
            break;
128
0
          }
129
460k
          in.increment_position(initial_inbytes_left - inbytes_left);
130
460k
        }
131
459k
      }
132
133
459k
      return stat;
134
459k
    }
135
136
  private:
137
    APRCharsetDecoder(const APRCharsetDecoder&);
138
    APRCharsetDecoder& operator=(const APRCharsetDecoder&);
139
    LOG4CXX_NS::helpers::Pool pool;
140
    std::mutex mutex;
141
    apr_xlate_t* convset;
142
};
143
144
#endif
145
146
#if LOG4CXX_LOGCHAR_IS_WCHAR && LOG4CXX_HAS_MBSRTOWCS
147
/**
148
*    Converts from the default multi-byte string to
149
*        LogString using mbstowcs.
150
*
151
*/
152
class MbstowcsCharsetDecoder : public CharsetDecoder
153
{
154
  public:
155
    MbstowcsCharsetDecoder()
156
0
    {
157
0
    }
158
159
    virtual ~MbstowcsCharsetDecoder()
160
0
    {
161
0
    }
162
163
  private:
164
    inline log4cxx_status_t append(LogString& out, const wchar_t* buf)
165
0
    {
166
0
      out.append(buf);
167
0
      return APR_SUCCESS;
168
0
    }
169
170
    virtual log4cxx_status_t decode(ByteBuffer& in,
171
      LogString& out)
172
0
    {
173
0
      log4cxx_status_t stat = APR_SUCCESS;
174
0
      enum { BUFSIZE = 256 };
175
0
      wchar_t wbuf[BUFSIZE];
176
0
      char cbuf[BUFSIZE*4];
177
0
178
0
      mbstate_t mbstate;
179
0
      memset(&mbstate, 0, sizeof(mbstate));
180
0
181
0
      while (in.remaining() > 0)
182
0
      {
183
0
        const char* src = in.current();
184
0
185
0
        if (*src == 0)
186
0
        {
187
0
          out.append(1, (logchar) 0);
188
0
          in.increment_position(1);
189
0
        }
190
0
        else
191
0
        {
192
0
          auto available = std::min(sizeof (cbuf) - 1, in.remaining());
193
0
          strncpy(cbuf, src, available);
194
0
          cbuf[available] = 0;
195
0
          src = cbuf;
196
0
          size_t wCharCount = mbsrtowcs(wbuf,
197
0
              &src,
198
0
              BUFSIZE - 1,
199
0
              &mbstate);
200
0
          // mbsrtowcs sets *src to nullptr when it consumes a null wide character.
201
0
          // Performing pointer arithmetic on that nullptr (src - cbuf) is undefined
202
0
          // behaviour, so recover the consumed byte count from the position of the
203
0
          // null that stopped the conversion instead.
204
0
          size_t converted;
205
0
          if (src == nullptr)
206
0
          {
207
0
            size_t nullPos = 0;
208
0
            while (nullPos < available && cbuf[nullPos] != 0)
209
0
            {
210
0
              ++nullPos;
211
0
            }
212
0
            // If the null came from the input bytes, it was consumed too;
213
0
            // if it is the sentinel we wrote at cbuf[available], stop at available.
214
0
            converted = (nullPos < available) ? nullPos + 1 : available;
215
0
          }
216
0
          else
217
0
          {
218
0
            converted = static_cast<size_t>(src - cbuf);
219
0
          }
220
0
          in.increment_position(converted);
221
0
222
0
          if (wCharCount == (size_t) -1) // Illegal byte sequence?
223
0
          {
224
0
            LogString msg(LOG4CXX_STR("Illegal byte sequence at "));
225
0
            msg.append(std::to_wstring(in.position()));
226
0
            msg.append(LOG4CXX_STR(" of "));
227
0
            msg.append(std::to_wstring(in.limit()));
228
0
            LogLog::warn(msg);
229
0
            stat = APR_BADCH;
230
0
            break;
231
0
          }
232
0
          else
233
0
          {
234
0
            // FIX: Check for incomplete sequence infinite loop.
235
0
            // If mbsrtowcs returns success (>=0) but converted 0 bytes while data remains,
236
0
            // we are stuck (e.g. incomplete multibyte char at EOF).
237
0
            if (converted == 0 && in.remaining() > 0)
238
0
            {
239
0
              LogString msg(LOG4CXX_STR("Incomplete multibyte sequence at end of buffer"));
240
0
              LogLog::warn(msg);
241
0
              stat = APR_BADCH;
242
0
              break; // Break the infinite loop
243
0
            }
244
0
245
0
            wbuf[wCharCount] = 0;
246
0
            stat = append(out, wbuf);
247
0
          }
248
0
        }
249
0
      }
250
0
251
0
      return stat;
252
0
    }
253
254
255
256
  private:
257
    MbstowcsCharsetDecoder(const MbstowcsCharsetDecoder&);
258
    MbstowcsCharsetDecoder& operator=(const MbstowcsCharsetDecoder&);
259
};
260
#endif
261
262
263
/**
264
*    Decoder used when the external and internal charsets
265
*    are the same.
266
*
267
*/
268
class TrivialCharsetDecoder : public CharsetDecoder
269
{
270
  public:
271
    TrivialCharsetDecoder()
272
3.40k
    {
273
3.40k
    }
274
275
    virtual ~TrivialCharsetDecoder()
276
0
    {
277
0
    }
278
279
    virtual log4cxx_status_t decode(ByteBuffer& in,
280
      LogString& out)
281
15.4k
    {
282
15.4k
      size_t remaining = in.remaining();
283
284
15.4k
      if ( remaining > 0)
285
15.0k
      {
286
15.0k
        auto src = in.current();
287
15.0k
        auto count = remaining / sizeof(logchar);
288
15.0k
        out.append(reinterpret_cast<const logchar*>(src), count);
289
15.0k
        in.increment_position(remaining);
290
15.0k
      }
291
292
15.4k
      return APR_SUCCESS;
293
15.4k
    }
log4cxx::helpers::TrivialCharsetDecoder::decode(log4cxx::helpers::ByteBuffer&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
Line
Count
Source
281
15.4k
    {
282
15.4k
      size_t remaining = in.remaining();
283
284
15.4k
      if ( remaining > 0)
285
15.0k
      {
286
15.0k
        auto src = in.current();
287
15.0k
        auto count = remaining / sizeof(logchar);
288
15.0k
        out.append(reinterpret_cast<const logchar*>(src), count);
289
15.0k
        in.increment_position(remaining);
290
15.0k
      }
291
292
15.4k
      return APR_SUCCESS;
293
15.4k
    }
Unexecuted instantiation: log4cxx::helpers::TrivialCharsetDecoder::decode(log4cxx::helpers::ByteBuffer&, std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >&)
294
295
296
297
  private:
298
    TrivialCharsetDecoder(const TrivialCharsetDecoder&);
299
    TrivialCharsetDecoder& operator=(const TrivialCharsetDecoder&);
300
};
301
302
/**
303
*    Converts from UTF-8 to LogString
304
*
305
*/
306
class UTF8CharsetDecoder : public CharsetDecoder
307
{
308
  public:
309
    UTF8CharsetDecoder()
310
2.41k
    {
311
2.41k
    }
312
313
    virtual ~UTF8CharsetDecoder()
314
0
    {
315
0
    }
316
317
  private:
318
    virtual log4cxx_status_t decode(ByteBuffer& in,
319
      LogString& out)
320
45.1M
    {
321
45.1M
      auto availableByteCount = in.remaining();
322
440M
      while (0 < availableByteCount)
323
440M
      {
324
440M
        auto sv = getUTF8CodePoint(in);
325
440M
        auto nextAvailableByteCount = in.remaining();
326
440M
        if (sv == 0xFFFF || nextAvailableByteCount == availableByteCount)
327
45.0M
          return APR_BADCH;
328
395M
        Transcoder::encode(sv, out);
329
395M
        availableByteCount = nextAvailableByteCount;
330
395M
      }
331
100k
      return APR_SUCCESS;
332
45.1M
    }
Unexecuted instantiation: log4cxx::helpers::UTF8CharsetDecoder::decode(log4cxx::helpers::ByteBuffer&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
log4cxx::helpers::UTF8CharsetDecoder::decode(log4cxx::helpers::ByteBuffer&, std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >&)
Line
Count
Source
320
45.1M
    {
321
45.1M
      auto availableByteCount = in.remaining();
322
440M
      while (0 < availableByteCount)
323
440M
      {
324
440M
        auto sv = getUTF8CodePoint(in);
325
440M
        auto nextAvailableByteCount = in.remaining();
326
440M
        if (sv == 0xFFFF || nextAvailableByteCount == availableByteCount)
327
45.0M
          return APR_BADCH;
328
395M
        Transcoder::encode(sv, out);
329
395M
        availableByteCount = nextAvailableByteCount;
330
395M
      }
331
100k
      return APR_SUCCESS;
332
45.1M
    }
333
334
  private:
335
    UTF8CharsetDecoder(const UTF8CharsetDecoder&);
336
    UTF8CharsetDecoder& operator=(const UTF8CharsetDecoder&);
337
};
338
339
/**
340
*    Converts from ISO-8859-1 to LogString.
341
*
342
*/
343
class ISOLatinCharsetDecoder : public CharsetDecoder
344
{
345
  public:
346
    ISOLatinCharsetDecoder()
347
471
    {
348
471
    }
349
350
    virtual ~ISOLatinCharsetDecoder()
351
0
    {
352
0
    }
353
354
  private:
355
    virtual log4cxx_status_t decode(ByteBuffer& in,
356
      LogString& out)
357
928
    {
358
928
      auto availableByteCount = in.remaining();
359
928
      auto src = in.current();
360
928
      auto srcEnd = src + availableByteCount;
361
362
2.03M
      while (src < srcEnd)
363
2.02M
      {
364
2.02M
        auto sv = static_cast<unsigned int>(static_cast<unsigned char>(*src++));
365
2.02M
        Transcoder::encode(sv, out);
366
2.02M
      }
367
928
      in.increment_position(availableByteCount);
368
369
928
      return APR_SUCCESS;
370
928
    }
log4cxx::helpers::ISOLatinCharsetDecoder::decode(log4cxx::helpers::ByteBuffer&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
Line
Count
Source
357
471
    {
358
471
      auto availableByteCount = in.remaining();
359
471
      auto src = in.current();
360
471
      auto srcEnd = src + availableByteCount;
361
362
786k
      while (src < srcEnd)
363
786k
      {
364
786k
        auto sv = static_cast<unsigned int>(static_cast<unsigned char>(*src++));
365
786k
        Transcoder::encode(sv, out);
366
786k
      }
367
471
      in.increment_position(availableByteCount);
368
369
471
      return APR_SUCCESS;
370
471
    }
log4cxx::helpers::ISOLatinCharsetDecoder::decode(log4cxx::helpers::ByteBuffer&, std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >&)
Line
Count
Source
357
457
    {
358
457
      auto availableByteCount = in.remaining();
359
457
      auto src = in.current();
360
457
      auto srcEnd = src + availableByteCount;
361
362
1.24M
      while (src < srcEnd)
363
1.24M
      {
364
1.24M
        auto sv = static_cast<unsigned int>(static_cast<unsigned char>(*src++));
365
1.24M
        Transcoder::encode(sv, out);
366
1.24M
      }
367
457
      in.increment_position(availableByteCount);
368
369
457
      return APR_SUCCESS;
370
457
    }
371
372
373
374
  private:
375
    ISOLatinCharsetDecoder(const ISOLatinCharsetDecoder&);
376
    ISOLatinCharsetDecoder& operator=(const ISOLatinCharsetDecoder&);
377
};
378
379
380
/**
381
*    Converts from US-ASCII to LogString.
382
*
383
*/
384
class USASCIICharsetDecoder : public CharsetDecoder
385
{
386
  public:
387
    USASCIICharsetDecoder()
388
494
    {
389
494
    }
390
391
    virtual ~USASCIICharsetDecoder()
392
0
    {
393
0
    }
394
395
  private:
396
397
    virtual log4cxx_status_t decode(ByteBuffer& in,
398
      LogString& out)
399
953k
    {
400
953k
      log4cxx_status_t stat = APR_SUCCESS;
401
402
953k
      auto availableByteCount = in.remaining();
403
953k
      auto src = in.current();
404
953k
      auto srcEnd = src + availableByteCount;
405
953k
      size_t byteCount = 0;
406
2.39M
      while (src < srcEnd)
407
2.39M
      {
408
2.39M
        auto sv = static_cast<unsigned int>(*src++);
409
410
2.39M
        if (sv < 0x80)
411
1.44M
        {
412
1.44M
          ++byteCount;
413
1.44M
          Transcoder::encode(sv, out);
414
1.44M
        }
415
953k
        else
416
953k
        {
417
953k
          stat = APR_BADCH;
418
953k
          break;
419
953k
        }
420
2.39M
      }
421
953k
      in.increment_position(byteCount);
422
423
953k
      return stat;
424
953k
    }
log4cxx::helpers::USASCIICharsetDecoder::decode(log4cxx::helpers::ByteBuffer&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
Line
Count
Source
399
246k
    {
400
246k
      log4cxx_status_t stat = APR_SUCCESS;
401
402
246k
      auto availableByteCount = in.remaining();
403
246k
      auto src = in.current();
404
246k
      auto srcEnd = src + availableByteCount;
405
246k
      size_t byteCount = 0;
406
1.02M
      while (src < srcEnd)
407
1.02M
      {
408
1.02M
        auto sv = static_cast<unsigned int>(*src++);
409
410
1.02M
        if (sv < 0x80)
411
780k
        {
412
780k
          ++byteCount;
413
780k
          Transcoder::encode(sv, out);
414
780k
        }
415
246k
        else
416
246k
        {
417
246k
          stat = APR_BADCH;
418
246k
          break;
419
246k
        }
420
1.02M
      }
421
246k
      in.increment_position(byteCount);
422
423
246k
      return stat;
424
246k
    }
log4cxx::helpers::USASCIICharsetDecoder::decode(log4cxx::helpers::ByteBuffer&, std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >&)
Line
Count
Source
399
706k
    {
400
706k
      log4cxx_status_t stat = APR_SUCCESS;
401
402
706k
      auto availableByteCount = in.remaining();
403
706k
      auto src = in.current();
404
706k
      auto srcEnd = src + availableByteCount;
405
706k
      size_t byteCount = 0;
406
1.36M
      while (src < srcEnd)
407
1.36M
      {
408
1.36M
        auto sv = static_cast<unsigned int>(*src++);
409
410
1.36M
        if (sv < 0x80)
411
660k
        {
412
660k
          ++byteCount;
413
660k
          Transcoder::encode(sv, out);
414
660k
        }
415
706k
        else
416
706k
        {
417
706k
          stat = APR_BADCH;
418
706k
          break;
419
706k
        }
420
1.36M
      }
421
706k
      in.increment_position(byteCount);
422
423
706k
      return stat;
424
706k
    }
425
426
427
428
  private:
429
    USASCIICharsetDecoder(const USASCIICharsetDecoder&);
430
    USASCIICharsetDecoder& operator=(const USASCIICharsetDecoder&);
431
};
432
433
/**
434
 *    Charset decoder that uses current locale settings.
435
 */
436
class LocaleCharsetDecoder : public CharsetDecoder
437
{
438
  public:
439
0
    LocaleCharsetDecoder() : state()
440
0
    {
441
0
    }
442
    log4cxx_status_t decode(ByteBuffer& in, LogString& out) override
443
0
    {
444
0
      log4cxx_status_t result = APR_SUCCESS;
445
0
      auto p = in.current();
446
0
      auto availableByteCount = in.remaining();
447
0
      size_t byteCount = 0;
448
0
#if !LOG4CXX_CHARSET_EBCDIC
449
0
      if (std::mbsinit(&this->state)) // ByteBuffer not partially decoded?
450
0
      {
451
        // Copy single byte characters
452
0
        for (; byteCount < availableByteCount && static_cast<unsigned int>(*p) < 0x80; ++byteCount, ++p)
453
0
        {
454
0
          out.append(1, *p);
455
0
        }
456
0
      }
457
0
#endif
458
      // Decode characters that may be represented by multiple bytes
459
0
      while (byteCount < availableByteCount)
460
0
      {
461
0
        wchar_t ch = 0;
462
0
        size_t n = std::mbrtowc(&ch, p, availableByteCount - byteCount, &this->state);
463
0
        if (0 == n) // NULL encountered?
464
0
        {
465
0
          ++byteCount;
466
0
          break;
467
0
        }
468
0
        if (static_cast<std::size_t>(-1) == n) // decoding error?
469
0
        {
470
0
          result = APR_BADCH;
471
0
          break;
472
0
        }
473
0
        if (static_cast<std::size_t>(-2) == n) // incomplete sequence?
474
0
        {
475
0
          break;
476
0
        }
477
0
        Transcoder::encode(static_cast<unsigned int>(ch), out);
478
0
        byteCount += n;
479
0
        p += n;
480
0
      }
481
0
      in.increment_position(byteCount);
482
0
      return result;
483
0
    }
Unexecuted instantiation: log4cxx::helpers::LocaleCharsetDecoder::decode(log4cxx::helpers::ByteBuffer&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
Unexecuted instantiation: log4cxx::helpers::LocaleCharsetDecoder::decode(log4cxx::helpers::ByteBuffer&, std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >&)
484
485
  private:
486
    std::mbstate_t state;
487
};
488
489
490
491
} // namespace helpers
492
493
}  //namespace log4cxx
494
495
496
CharsetDecoder::CharsetDecoder()
497
7.59k
{
498
7.59k
}
499
500
501
CharsetDecoder::~CharsetDecoder()
502
7.59k
{
503
7.59k
}
504
505
CharsetDecoder* CharsetDecoder::createDefaultDecoder()
506
8
{
507
8
#if LOG4CXX_CHARSET_UTF8
508
8
#if LOG4CXX_LOGCHAR_IS_UTF8
509
8
  return new TrivialCharsetDecoder();
510
#else
511
  return new UTF8CharsetDecoder();
512
#endif
513
#elif LOG4CXX_CHARSET_ISO88591 || defined(_WIN32_WCE)
514
  return new ISOLatinCharsetDecoder();
515
#elif LOG4CXX_CHARSET_USASCII
516
  return new USASCIICharsetDecoder();
517
#elif LOG4CXX_LOGCHAR_IS_WCHAR && LOG4CXX_HAS_MBSRTOWCS
518
  return new MbstowcsCharsetDecoder();
519
#else
520
  return new LocaleCharsetDecoder();
521
#endif
522
8
}
523
524
CharsetDecoderPtr CharsetDecoder::getDefaultDecoder()
525
8
{
526
8
  static WideLife<CharsetDecoderPtr> decoder(createDefaultDecoder());
527
528
  //
529
  //  if invoked after static variable destruction
530
  //     (if logging is called in the destructor of a static object)
531
  //     then create a new decoder.
532
  //
533
8
  if (decoder.value() == 0)
534
0
  {
535
0
    return CharsetDecoderPtr( createDefaultDecoder() );
536
0
  }
537
538
8
  return decoder;
539
8
}
540
541
CharsetDecoderPtr CharsetDecoder::getUTF8Decoder()
542
0
{
543
0
  return std::make_shared<UTF8CharsetDecoder>();
544
0
}
545
546
CharsetDecoderPtr CharsetDecoder::getISOLatinDecoder()
547
2
{
548
2
  return std::make_shared<ISOLatinCharsetDecoder>();
549
2
}
550
551
552
CharsetDecoderPtr CharsetDecoder::getDecoder(const LogString& charset)
553
7.58k
{
554
7.58k
  if (StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("UTF-8"), LOG4CXX_STR("utf-8")) ||
555
1.77k
    StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("UTF8"), LOG4CXX_STR("utf8")) ||
556
1.77k
    StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("CP65001"), LOG4CXX_STR("cp65001")))
557
5.80k
  {
558
#if LOG4CXX_LOGCHAR_IS_UTF8
559
    return std::make_shared<TrivialCharsetDecoder>();
560
#else
561
    return std::make_shared<UTF8CharsetDecoder>();
562
#endif
563
5.80k
  }
564
1.77k
  else if (StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("C"), LOG4CXX_STR("c")) ||
565
1.77k
    charset == LOG4CXX_STR("646") ||
566
1.77k
    StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("US-ASCII"), LOG4CXX_STR("us-ascii")) ||
567
1.28k
    StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("ISO646-US"), LOG4CXX_STR("iso646-US")) ||
568
1.28k
    StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("ANSI_X3.4-1968"), LOG4CXX_STR("ansi_x3.4-1968")) ||
569
1.28k
    StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("CP20127"), LOG4CXX_STR("cp20127")))
570
494
  {
571
494
    return std::make_shared<USASCIICharsetDecoder>();
572
494
  }
573
1.28k
  else if (StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("ISO-8859-1"), LOG4CXX_STR("iso-8859-1")) ||
574
814
    StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("ISO-LATIN-1"), LOG4CXX_STR("iso-latin-1")) ||
575
814
    StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("CP1252"), LOG4CXX_STR("cp1252")))
576
469
  {
577
469
    return std::make_shared<ISOLatinCharsetDecoder>();
578
469
  }
579
814
  else if (StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("LOCALE"), LOG4CXX_STR("locale")))
580
0
  {
581
0
    return std::make_shared<LocaleCharsetDecoder>();
582
0
  }
583
584
814
#if APR_HAS_XLATE
585
814
  return std::make_shared<APRCharsetDecoder>(charset);
586
#else
587
  throw IllegalArgumentException(charset);
588
#endif
589
7.58k
}
log4cxx::helpers::CharsetDecoder::getDecoder(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Line
Count
Source
553
4.29k
{
554
4.29k
  if (StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("UTF-8"), LOG4CXX_STR("utf-8")) ||
555
890
    StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("UTF8"), LOG4CXX_STR("utf8")) ||
556
890
    StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("CP65001"), LOG4CXX_STR("cp65001")))
557
3.40k
  {
558
3.40k
#if LOG4CXX_LOGCHAR_IS_UTF8
559
3.40k
    return std::make_shared<TrivialCharsetDecoder>();
560
#else
561
    return std::make_shared<UTF8CharsetDecoder>();
562
#endif
563
3.40k
  }
564
890
  else if (StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("C"), LOG4CXX_STR("c")) ||
565
890
    charset == LOG4CXX_STR("646") ||
566
890
    StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("US-ASCII"), LOG4CXX_STR("us-ascii")) ||
567
647
    StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("ISO646-US"), LOG4CXX_STR("iso646-US")) ||
568
647
    StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("ANSI_X3.4-1968"), LOG4CXX_STR("ansi_x3.4-1968")) ||
569
647
    StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("CP20127"), LOG4CXX_STR("cp20127")))
570
243
  {
571
243
    return std::make_shared<USASCIICharsetDecoder>();
572
243
  }
573
647
  else if (StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("ISO-8859-1"), LOG4CXX_STR("iso-8859-1")) ||
574
411
    StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("ISO-LATIN-1"), LOG4CXX_STR("iso-latin-1")) ||
575
411
    StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("CP1252"), LOG4CXX_STR("cp1252")))
576
236
  {
577
236
    return std::make_shared<ISOLatinCharsetDecoder>();
578
236
  }
579
411
  else if (StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("LOCALE"), LOG4CXX_STR("locale")))
580
0
  {
581
0
    return std::make_shared<LocaleCharsetDecoder>();
582
0
  }
583
584
411
#if APR_HAS_XLATE
585
411
  return std::make_shared<APRCharsetDecoder>(charset);
586
#else
587
  throw IllegalArgumentException(charset);
588
#endif
589
4.29k
}
log4cxx::helpers::CharsetDecoder::getDecoder(std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > const&)
Line
Count
Source
553
3.29k
{
554
3.29k
  if (StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("UTF-8"), LOG4CXX_STR("utf-8")) ||
555
887
    StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("UTF8"), LOG4CXX_STR("utf8")) ||
556
887
    StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("CP65001"), LOG4CXX_STR("cp65001")))
557
2.40k
  {
558
#if LOG4CXX_LOGCHAR_IS_UTF8
559
    return std::make_shared<TrivialCharsetDecoder>();
560
#else
561
2.40k
    return std::make_shared<UTF8CharsetDecoder>();
562
2.40k
#endif
563
2.40k
  }
564
887
  else if (StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("C"), LOG4CXX_STR("c")) ||
565
887
    charset == LOG4CXX_STR("646") ||
566
887
    StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("US-ASCII"), LOG4CXX_STR("us-ascii")) ||
567
636
    StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("ISO646-US"), LOG4CXX_STR("iso646-US")) ||
568
636
    StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("ANSI_X3.4-1968"), LOG4CXX_STR("ansi_x3.4-1968")) ||
569
636
    StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("CP20127"), LOG4CXX_STR("cp20127")))
570
251
  {
571
251
    return std::make_shared<USASCIICharsetDecoder>();
572
251
  }
573
636
  else if (StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("ISO-8859-1"), LOG4CXX_STR("iso-8859-1")) ||
574
403
    StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("ISO-LATIN-1"), LOG4CXX_STR("iso-latin-1")) ||
575
403
    StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("CP1252"), LOG4CXX_STR("cp1252")))
576
233
  {
577
233
    return std::make_shared<ISOLatinCharsetDecoder>();
578
233
  }
579
403
  else if (StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("LOCALE"), LOG4CXX_STR("locale")))
580
0
  {
581
0
    return std::make_shared<LocaleCharsetDecoder>();
582
0
  }
583
584
403
#if APR_HAS_XLATE
585
403
  return std::make_shared<APRCharsetDecoder>(charset);
586
#else
587
  throw IllegalArgumentException(charset);
588
#endif
589
3.29k
}
590
591
log4cxx_status_t CharsetDecoder::decode(const char* in, size_t maxByteCount, LogString& out)
592
16.2k
{
593
16.2k
  ByteBuffer buf((char*)in, strnlen_s(in, maxByteCount));
594
16.2k
  return decode(buf, out);
595
16.2k
}
log4cxx::helpers::CharsetDecoder::decode(char const*, unsigned long, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
Line
Count
Source
592
15.1k
{
593
15.1k
  ByteBuffer buf((char*)in, strnlen_s(in, maxByteCount));
594
15.1k
  return decode(buf, out);
595
15.1k
}
log4cxx::helpers::CharsetDecoder::decode(char const*, unsigned long, std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >&)
Line
Count
Source
592
1.08k
{
593
1.08k
  ByteBuffer buf((char*)in, strnlen_s(in, maxByteCount));
594
1.08k
  return decode(buf, out);
595
1.08k
}
596
597
unsigned int CharsetDecoder::getUTF8CodePoint(ByteBuffer& in)
598
480M
{
599
480M
  auto availableByteCount = in.remaining();
600
480M
  if (0 == availableByteCount)
601
0
    return 0xFFFF;
602
603
480M
  auto pChar = in.current();
604
480M
  auto ch1 = static_cast<unsigned char>(*pChar);
605
480M
  if (ch1 <= 0x7F)
606
423M
  {
607
423M
    in.increment_position(1);
608
423M
    return ch1;
609
423M
  }
610
611
  //
612
  //   should not have continuation character here
613
  //
614
56.6M
  if ((ch1 & 0xC0) != 0x80 && 1 < availableByteCount)
615
25.0M
  {
616
25.0M
    auto ch2 = static_cast<unsigned char>(*(pChar + 1));
617
25.0M
    if ((ch2 & 0xC0) != 0x80) // not a continuation?
618
19.7M
      return 0xFFFF;
619
620
5.35M
    if ((ch1 & 0xE0) == 0xC0)
621
720k
    {
622
720k
      unsigned int rv = ((ch1 & 0x1F) << 6) + (ch2 & 0x3F);
623
720k
      if (rv >= 0x80)
624
611k
      {
625
611k
        in.increment_position(2);
626
611k
        return rv;
627
611k
      }
628
108k
      return 0xFFFF;
629
720k
    }
630
631
4.63M
    if (2 < availableByteCount)
632
4.62M
    {
633
4.62M
      auto ch3 = static_cast<unsigned char>(*(pChar + 2));
634
4.62M
      if ((ch3 & 0xC0) != 0x80) // not a continuation?
635
647k
        return 0xFFFF;
636
637
3.97M
      if ((ch1 & 0xF0) == 0xE0)
638
322k
      {
639
322k
        unsigned int rv = ((ch1 & 0x0F) << 12)
640
322k
          + ((ch2 & 0x3F) << 6)
641
322k
          + (ch3 & 0x3F);
642
643
        // RFC 3629 §3 prohibits UTF-8 encodings of the UTF-16 surrogate
644
        // halves (U+D800..U+DFFF); accepting them lets malformed Unicode
645
        // cross the decode boundary into LogString and downstream output.
646
322k
        if (rv < 0x800 || (0xD800 <= rv && rv <= 0xDFFF))
647
70.0k
          return 0xFFFF;
648
649
252k
        in.increment_position(3);
650
252k
        return rv;
651
322k
      }
652
653
3.65M
      if (3 < availableByteCount)
654
3.65M
      {
655
3.65M
        auto ch4 = static_cast<unsigned char>(*(pChar + 3));
656
3.65M
        if ((ch4 & 0xC0) != 0x80) // not a continuation?
657
230k
          return 0xFFFF;
658
659
3.42M
        unsigned int rv = ((ch1 & 0x07) << 18)
660
3.42M
          + ((ch2 & 0x3F) << 12)
661
3.42M
          + ((ch3 & 0x3F) << 6)
662
3.42M
          + (ch4 & 0x3F);
663
664
        // RFC 3629 §3 caps UTF-8 at U+10FFFF; lead bytes F5..F7 (and
665
        // F4 with an over-high trailer) produce rv > 0x10FFFF, which
666
        // is not a Unicode code point. Without this bound, encodeUTF16
667
        // later silently aliases the bogus value to a valid in-range
668
        // code point — a substitution-collision filter-bypass primitive.
669
        // Lead bytes F8..FF are never valid UTF-8, but the & 0x07 mask
670
        // discards their high bits, so without the (ch1 & 0xF8) == 0xF0
671
        // guard F8 BF BF BF would alias to U+3FFFF instead of being
672
        // rejected.
673
3.42M
        if ((ch1 & 0xF8) == 0xF0 && rv > 0xFFFF && rv <= 0x10FFFF)
674
3.20M
        {
675
3.20M
          in.increment_position(4);
676
3.20M
          return rv;
677
3.20M
        }
678
679
3.42M
      }
680
3.65M
    }
681
4.63M
  }
682
31.8M
  return 0xFFFF;
683
56.6M
}