Bug Summary

File:_build/../src/icu-decoder.cc
Warning:line 108, column 35
This statement is never executed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name icu-decoder.cc -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=none -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/_build -resource-dir /usr/lib/llvm-16/lib/clang/16 -I src/decoder-cat.p -I src -I ../src -I . -I .. -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -D _GLIBCXX_ASSERTIONS=1 -D _FILE_OFFSET_BITS=64 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/x86_64-linux-gnu/c++/13 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/backward -internal-isystem /usr/lib/llvm-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-address-of-packed-member -Wno-missing-field-initializers -Wno-packed -Wno-switch-enum -Wno-unused-parameter -Wwrite-strings -std=gnu++17 -fdeprecated-macro -fdebug-compilation-dir=/rootdir/_build -ferror-limit 19 -fvisibility=hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-08-05-222352-10670-1 -x c++ ../src/icu-decoder.cc
1/*
2 * Copyright © 2019 Christian Persch
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 3 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18#include "config.h"
19
20#include <glib.h>
21
22#include <cassert>
23#include <memory>
24
25#include "icu-decoder.hh"
26
27namespace bte::base {
28
29/*
30 * ICUDecoder::decode:
31 * @sptr: inout pointer to input data
32 * @flush: whether to flush
33 *
34 * Decodes input, and advances *@sptr for input consumed. At most
35 * one byte of input is consumed; if flushing, no input is consumed.
36 *
37 * Returns: whether there is an output character available
38 */
39ICUDecoder::Result
40ICUDecoder::decode(uint8_t const** sptr,
41 bool flush) noexcept
42{
43 switch (m_state) {
44 case State::eOutput:
45 if (++m_index < m_available)
46 return Result::eSomething;
47
48 m_state = State::eInput;
49 [[fallthrough]];
50 case State::eInput: {
51 /* Convert in two stages from charset to UTF-32, pivoting through UTF-16.
52 * This is similar to ucnv_convertEx(), but that API does not fit our
53 * requirements completely.
54 *
55 * This function is similar to ucnv_getNextUChar, except that it works
56 * with streaming (and thus may produce no output in some steps), while
57 * ucnv_getNextUChar does not.
58 */
59
60 auto source_ptr = reinterpret_cast<char const**>(sptr);
61 auto source_start = *source_ptr;
62 auto source_limit = source_start + (1 - flush);
63
64 auto target_u16_start = u16_buffer();
65 auto target_u16_limit = u16_buffer_end();
66 auto target_u16 = target_u16_start;
67
68 m_err.reset();
69 ucnv_toUnicodeucnv_toUnicode_72(m_charset_converter.get(),
70 &target_u16, target_u16_limit,
71 source_ptr, source_limit,
72 nullptr /* offsets */,
73 flush,
74 m_err);
75
76 /* There should be no error here. We use the default callback
77 * which replaces invalid input with replacment character (either
78 * U+FFFD or SUB), and we should never hit U_BUFFER_OVERFLOW_ERROR,
79 * since we process only one input byte at a time and the output
80 * buffer holds at most 1 UTF-16 character (a high surrogate), and
81 * there are no charsets where the state is so deep as to suddently
82 * output 32 characters.
83 */
84 if (m_err.isFailure()) {
85 m_state = State::eError;
86 return Result::eError;
87 }
88
89 /* Now convert from UTF-16 to UTF-32. There will be no overflow here
90 * either, since the output buffer is empty, and for each UTF-16 code
91 * point of input, the decoder will output at most one UTF-32 code
92 * point.
93 */
94
95 auto target_u32_start = reinterpret_cast<char*>(u32_buffer());
96 auto target_u32_limit = reinterpret_cast<char const*>(u32_buffer_end());
97 auto target_u32 = target_u32_start;
98 auto target_u16_u32_start = const_cast<char16_t const*>(target_u16_start);
99 auto target_u16_u32_limit = target_u16;
100
101 ucnv_fromUnicodeucnv_fromUnicode_72(m_u32_converter.get(),
102 &target_u32, target_u32_limit,
103 &target_u16_u32_start, target_u16_u32_limit,
104 nullptr /* offsets */,
105 flush,
106 m_err);
107 if (m_err.isFailure()) {
108 m_state = State::eError;
This statement is never executed
109 return Result::eError;
110 }
111
112 if (target_u32 == target_u32_start) {
113 if (*source_ptr == source_start && !flush) {
114 /* The decoder produced neither output nor consumed input, and
115 * wan't flushing? That shouldn't happen; go to error state,
116 * requiring an explicit reset() to proceed further.
117 */
118 m_state = State::eError;
119 return Result::eError;
120 }
121
122 return Result::eNothing;
123 }
124
125 /* We have some output! */
126 assert((target_u32 - target_u32_start) % sizeof(m_u32_buffer[0]) == 0)(static_cast <bool> ((target_u32 - target_u32_start) % sizeof
(m_u32_buffer[0]) == 0) ? void (0) : __assert_fail ("(target_u32 - target_u32_start) % sizeof(m_u32_buffer[0]) == 0"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
127 m_available = (target_u32 - target_u32_start) / sizeof(m_u32_buffer[0]);
128 assert(m_available >= 1)(static_cast <bool> (m_available >= 1) ? void (0) : __assert_fail
("m_available >= 1", __builtin_FILE (), __builtin_LINE ()
, __extension__ __PRETTY_FUNCTION__))
;
129
130 m_index = 0;
131 return Result::eSomething;
132 }
133
134 case State::eError:
135 default:
136 return Result::eError;
137 }
138}
139
140void
141ICUDecoder::reset() noexcept
142{
143 ucnv_resetToUnicodeucnv_resetToUnicode_72(m_charset_converter.get());
144 ucnv_resetFromUnicodeucnv_resetFromUnicode_72(m_u32_converter.get());
145 m_err.reset();
146 m_state = State::eInput;
147 m_available = 0;
148 m_index = 0;
149}
150
151} // namespace bte::base