Bug Summary

File:/rootdir/_build/../src/ringview.cc
Warning:line 279, column 26
Assigned value is garbage or undefined

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 ringview.cc -analyzer-store=region -analyzer-opt-analyze-nested-blocks -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 -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-14/lib/clang/14.0.6 -I src/libbte-2.91.so.0.6500.0.p -I src -I ../src -I . -I .. -I src/bte -I ../src/bte -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/pango-1.0 -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/uuid -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/p11-kit-1 -I /usr/include/ctk-3.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/atk-1.0 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -D _FILE_OFFSET_BITS=64 -D G_LOG_DOMAIN="BTE" -D LOCALEDIR="/usr/local/share/locale" -D BTE_DISABLE_DEPRECATION_WARNINGS -D BTE_COMPILATION -U PARSER_INCLUDE_NOP -D CDK_VERSION_MIN_REQUIRED=(G_ENCODE_VERSION(3,18)) -D CDK_VERSION_MAX_ALLOWED=(G_ENCODE_VERSION(3,20)) -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/x86_64-linux-gnu/c++/12 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/backward -internal-isystem /usr/lib/llvm-14/lib/clang/14.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/12/../../../../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/2022-08-07-225954-9680-1 -x c++ ../src/ringview.cc
1/*
2 * Copyright © 2018–2019 Egmont Koblinger
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 2.1 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 Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19#include <config.h>
20
21#include "bidi.hh"
22#include "debug.h"
23#include "btedefines.hh"
24#include "bteinternal.hh"
25
26using namespace bte::base;
27
28RingView::RingView()
29{
30 m_bidirunner = std::make_unique<BidiRunner>(this);
31}
32
33RingView::~RingView()
34{
35 pause();
36}
37
38/* Pausing a RingView frees up pretty much all of its memory.
39 *
40 * This is to be used when the terminal is unlikely to be painted or interacted with
41 * in the near future, e.g. the widget is unmapped. Not to be called too frequently,
42 * in order to avoid memory fragmentation.
43 *
44 * The RingView is resumed automatically on demand.
45 */
46void
47RingView::pause()
48{
49 int i;
50
51 if (m_paused)
52 return;
53
54 _bte_debug_print (BTE_DEBUG_RINGVIEW, "Ringview: pause, freeing %d rows, %d bidirows.\n",do { } while(0)
55 m_rows_alloc_len, m_bidirows_alloc_len)do { } while(0);
56
57 for (i = 0; i < m_rows_alloc_len; i++) {
58 _bte_row_data_fini(m_rows[i]);
59 g_free (m_rows[i]);
60 }
61 g_free (m_rows);
62 m_rows_alloc_len = 0;
63
64 for (i = 0; i < m_bidirows_alloc_len; i++) {
65 delete m_bidirows[i];
66 }
67 g_free (m_bidirows);
68 m_bidirows_alloc_len = 0;
69
70 m_invalid = true;
71 m_paused = true;
72}
73
74/* Allocate (again) the required memory. */
75void
76RingView::resume()
77{
78 g_assert_cmpint (m_len, >=, 1)do { gint64 __n1 = (m_len), __n2 = (1); if (__n1 >= __n2) ;
else g_assertion_message_cmpnum ("BTE", "../src/ringview.cc"
, 78, ((const char*) (__PRETTY_FUNCTION__)), "m_len" " " ">="
" " "1", (long double) __n1, ">=", (long double) __n2, 'i'
); } while (0)
;
6
Assuming '__n1' is >= '__n2'
7
Taking true branch
8
Loop condition is false. Exiting loop
79
80 /* +16: A bit of arbitrary heuristics to likely prevent a quickly following
81 * realloc for the required context lines. */
82 m_rows_alloc_len = m_len + 16;
83 m_rows = (BteRowData **) g_malloc (sizeof (BteRowData *) * m_rows_alloc_len);
9
Storing uninitialized value
84 for (int i = 0; i < m_rows_alloc_len; i++) {
10
Assuming 'i' is >= field 'm_rows_alloc_len'
11
Loop condition is false. Execution continues on line 94
85 m_rows[i] = (BteRowData *) g_malloc (sizeof (BteRowData));
86 _bte_row_data_init (m_rows[i]);
87 }
88
89 /* +2: Likely prevent a quickly following realloc.
90 * The number of lines of interest keeps jumping up and down by one
91 * due to per-pixel scrolling, and by another one due sometimes having
92 * to reshuffle another line below the bottom for the overflowing bits
93 * of the outline rectangle cursor. */
94 m_bidirows_alloc_len = m_len + 2;
95 m_bidirows = (BidiRow **) g_malloc (sizeof (BidiRow *) * m_bidirows_alloc_len);
96 for (int i = 0; i < m_bidirows_alloc_len; i++) {
12
Assuming 'i' is >= field 'm_bidirows_alloc_len'
13
Loop condition is false. Execution continues on line 100
97 m_bidirows[i] = new BidiRow();
98 }
99
100 _bte_debug_print (BTE_DEBUG_RINGVIEW, "Ringview: resume, allocating %d rows, %d bidirows\n",do { } while(0)
14
Loop condition is false. Exiting loop
101 m_rows_alloc_len, m_bidirows_alloc_len)do { } while(0);
102
103 m_paused = false;
104}
105
106void
107RingView::set_ring(Ring *ring)
108{
109 if (G_LIKELY (ring == m_ring)(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
ring == m_ring) _g_boolean_var_ = 1; else _g_boolean_var_ = 0
; _g_boolean_var_; }), 1))
)
110 return;
111
112 m_ring = ring;
113 m_invalid = true;
114}
115
116void
117RingView::set_width(bte::grid::column_t width)
118{
119 if (G_LIKELY (width == m_width)(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
width == m_width) _g_boolean_var_ = 1; else _g_boolean_var_ =
0; _g_boolean_var_; }), 1))
)
120 return;
121
122 m_width = width;
123 m_invalid = true;
124}
125
126void
127RingView::set_rows(bte::grid::row_t start, bte::grid::row_t len)
128{
129 /* Force at least 1 row, see bug 134. */
130 len = MAX(len, 1)(((len) > (1)) ? (len) : (1));
131
132 if (start == m_start && len == m_len)
133 return;
134
135 /* With per-pixel scrolling, the desired viewport often shrinks by
136 * one row at one end, and remains the same at the other end.
137 * Save work by just keeping the current valid data in this case. */
138 if (!m_invalid && start >= m_start && start + len <= m_start + m_len)
139 return;
140
141 /* m_rows is expanded on demand in update() */
142
143 /* m_bidirows needs exactly this many lines */
144 if (G_UNLIKELY (!m_paused && len > m_bidirows_alloc_len)(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
!m_paused && len > m_bidirows_alloc_len) _g_boolean_var_
= 1; else _g_boolean_var_ = 0; _g_boolean_var_; }), 0))
) {
145 int i = m_bidirows_alloc_len;
146 while (len > m_bidirows_alloc_len) {
147 /* Don't realloc too aggressively. */
148 m_bidirows_alloc_len = std::max(m_bidirows_alloc_len + 1, m_bidirows_alloc_len * 5 / 4 /* whatever */);
149 }
150 _bte_debug_print (BTE_DEBUG_RINGVIEW, "Ringview: reallocate to %d bidirows\n",do { } while(0)
151 m_bidirows_alloc_len)do { } while(0);
152 m_bidirows = (BidiRow **) g_realloc (m_bidirows, sizeof (BidiRow *) * m_bidirows_alloc_len);
153 for (; i < m_bidirows_alloc_len; i++) {
154 m_bidirows[i] = new BidiRow();
155 }
156 }
157
158 m_start = start;
159 m_len = len;
160 m_invalid = true;
161}
162
163BteRowData const*
164RingView::get_row(bte::grid::row_t row) const
165{
166 g_assert_cmpint(row, >=, m_top)do { gint64 __n1 = (row), __n2 = (m_top); if (__n1 >= __n2
) ; else g_assertion_message_cmpnum ("BTE", "../src/ringview.cc"
, 166, ((const char*) (__PRETTY_FUNCTION__)), "row" " " ">="
" " "m_top", (long double) __n1, ">=", (long double) __n2
, 'i'); } while (0)
;
167 g_assert_cmpint(row, <, m_top + m_rows_len)do { gint64 __n1 = (row), __n2 = (m_top + m_rows_len); if (__n1
< __n2) ; else g_assertion_message_cmpnum ("BTE", "../src/ringview.cc"
, 167, ((const char*) (__PRETTY_FUNCTION__)), "row" " " "<"
" " "m_top + m_rows_len", (long double) __n1, "<", (long double
) __n2, 'i'); } while (0)
;
168
169 return m_rows[row - m_top];
170}
171
172void
173RingView::set_enable_bidi(bool enable_bidi)
174{
175 if (G_LIKELY (enable_bidi == m_enable_bidi)(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
enable_bidi == m_enable_bidi) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))
)
176 return;
177
178 m_enable_bidi = enable_bidi;
179 m_invalid = true;
180}
181
182void
183RingView::set_enable_shaping(bool enable_shaping)
184{
185 if (G_LIKELY (enable_shaping == m_enable_shaping)(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
enable_shaping == m_enable_shaping) _g_boolean_var_ = 1; else
_g_boolean_var_ = 0; _g_boolean_var_; }), 1))
)
186 return;
187
188 m_enable_shaping = enable_shaping;
189 m_invalid = true;
190}
191
192void
193RingView::update()
194{
195 if (!m_invalid)
1
Assuming field 'm_invalid' is true
2
Taking false branch
196 return;
197 if (m_paused)
3
Assuming field 'm_paused' is true
4
Taking true branch
198 resume();
5
Calling 'RingView::resume'
15
Returning from 'RingView::resume'
199
200 /* Find the beginning of the topmost paragraph.
201 *
202 * Extract at most BTE_RINGVIEW_PARAGRAPH_LENGTH_MAX context rows.
203 * If this safety limit is reached then together with the first
204 * non-context row this paragraph fragment is already longer
205 * than BTE_RINGVIEW_PARAGRAPH_LENGTH_MAX lines, and thus the
206 * BiDi code will skip it. */
207 bte::grid::row_t row = m_start;
208 const BteRowData *row_data;
209
210 _bte_debug_print (BTE_DEBUG_RINGVIEW, "Ringview: updating for [%ld..%ld] (%ld rows).\n",do { } while(0)
16
Loop condition is false. Exiting loop
211 m_start, m_start + m_len - 1, m_len)do { } while(0);
212
213 int i = BTE_RINGVIEW_PARAGRAPH_LENGTH_MAX500;
214 while (i--) {
17
Loop condition is true. Entering loop body
20
Loop condition is true. Entering loop body
215 if (!m_ring->is_soft_wrapped(row - 1))
18
Assuming the condition is false
19
Taking false branch
21
Assuming the condition is true
22
Taking true branch
216 break;
23
Execution continues on line 228
217 row--;
218 }
219
220 /* Extract the data beginning at the found row.
221 *
222 * Extract at most BTE_RINGVIEW_PARAGRAPH_LENGTH_MAX rows
223 * beyond the end of the specified area. Again, if this safety
224 * limit is reached then together with the last non-context row
225 * this paragraph fragment is already longer than
226 * BTE_RINGVIEW_PARAGRAPH_LENGTH_MAX lines, and thus the
227 * BiDi code will skip it. */
228 m_top = row;
229 m_rows_len = 0;
230 while (row < m_start + m_len + BTE_RINGVIEW_PARAGRAPH_LENGTH_MAX500) {
24
Assuming the condition is false
25
Loop condition is false. Execution continues on line 271
231 if (G_UNLIKELY (m_rows_len == m_rows_alloc_len)(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
m_rows_len == m_rows_alloc_len) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 0))
) {
232 /* Don't realloc too aggressively. */
233 m_rows_alloc_len = std::max(m_rows_alloc_len + 1, m_rows_alloc_len * 5 / 4 /* whatever */);
234 _bte_debug_print (BTE_DEBUG_RINGVIEW, "Ringview: reallocate to %d rows\n",do { } while(0)
235 m_rows_alloc_len)do { } while(0);
236 m_rows = (BteRowData **) g_realloc (m_rows, sizeof (BteRowData *) * m_rows_alloc_len);
237 for (int j = m_rows_len; j < m_rows_alloc_len; j++) {
238 m_rows[j] = (BteRowData *) g_malloc (sizeof (BteRowData));
239 _bte_row_data_init (m_rows[j]);
240 }
241 }
242
243 row_data = _bte_ring_contains(m_ring, row) ? m_ring->index(row) : nullptr;
244 if (G_LIKELY (row_data != nullptr)(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
row_data != nullptr) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))
) {
245 _bte_row_data_copy (row_data, m_rows[m_rows_len]);
246 /* Make sure that the extracted data is not wider than the screen,
247 * something that can happen if the window was narrowed with rewrapping disabled.
248 * Also make sure that we won't end up with unfinished characters.
249 * FIXME remove this once bug 135 is addressed. */
250 if (G_UNLIKELY (_bte_row_data_length(m_rows[m_rows_len]) > m_width)(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
((m_rows[m_rows_len])->len + 0) > m_width) _g_boolean_var_
= 1; else _g_boolean_var_ = 0; _g_boolean_var_; }), 0))
) {
251 int j = m_width;
252 while (j > 0) {
253 BteCell const* cell = _bte_row_data_get(m_rows[m_rows_len], j);
254 if (!cell->attr.fragment())
255 break;
256 j--;
257 }
258 _bte_row_data_shrink(m_rows[m_rows_len], j);
259 }
260 } else {
261 _bte_row_data_clear (m_rows[m_rows_len]);
262 }
263 m_rows_len++;
264 row++;
265
266 /* Once the bottom of the specified area is reached, stop at a hard newline. */
267 if (row >= m_start + m_len && (!row_data || !row_data->attr.soft_wrapped))
268 break;
269 }
270
271 _bte_debug_print (BTE_DEBUG_RINGVIEW, "Ringview: extracted %ld+%ld context lines: [%ld..%ld] (%d rows).\n",do { } while(0)
26
Loop condition is false. Exiting loop
272 m_start - m_top, (m_top + m_rows_len) - (m_start + m_len),do { } while(0)
273 m_top, m_top + m_rows_len - 1, m_rows_len)do { } while(0);
274
275 /* Loop through paragraphs of the extracted text, and do whatever we need to do on each paragraph. */
276 auto top = m_top;
277 row = top;
278 while (row < m_top + m_rows_len) {
27
Assuming the condition is true
28
Loop condition is true. Entering loop body
279 row_data = m_rows[row - m_top];
29
Assigned value is garbage or undefined
280 if (!row_data->attr.soft_wrapped || row == m_top + m_rows_len - 1) {
281 /* Found a paragraph from @top to @row, inclusive. */
282
283 /* Run the BiDi algorithm. */
284 m_bidirunner->paragraph(top, row + 1,
285 m_enable_bidi, m_enable_shaping);
286
287 /* Doing syntax highlighting etc. come here in the future. */
288
289 top = row + 1;
290 }
291 row++;
292 }
293
294 m_invalid = false;
295}
296
297BidiRow const* RingView::get_bidirow(bte::grid::row_t row) const
298{
299 g_assert_cmpint (row, >=, m_start)do { gint64 __n1 = (row), __n2 = (m_start); if (__n1 >= __n2
) ; else g_assertion_message_cmpnum ("BTE", "../src/ringview.cc"
, 299, ((const char*) (__PRETTY_FUNCTION__)), "row" " " ">="
" " "m_start", (long double) __n1, ">=", (long double) __n2
, 'i'); } while (0)
;
300 g_assert_cmpint (row, <, m_start + m_len)do { gint64 __n1 = (row), __n2 = (m_start + m_len); if (__n1 <
__n2) ; else g_assertion_message_cmpnum ("BTE", "../src/ringview.cc"
, 300, ((const char*) (__PRETTY_FUNCTION__)), "row" " " "<"
" " "m_start + m_len", (long double) __n1, "<", (long double
) __n2, 'i'); } while (0)
;
301 g_assert_false (m_invalid)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (!(m_invalid)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message ("BTE"
, "../src/ringview.cc", 301, ((const char*) (__PRETTY_FUNCTION__
)), "'" "m_invalid" "' should be FALSE"); } while (0)
;
302 g_assert_false (m_paused)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (!(m_paused)) _g_boolean_var_ = 1; else _g_boolean_var_ =
0; _g_boolean_var_; }), 1)) ; else g_assertion_message ("BTE"
, "../src/ringview.cc", 302, ((const char*) (__PRETTY_FUNCTION__
)), "'" "m_paused" "' should be FALSE"); } while (0)
;
303
304 return m_bidirows[row - m_start];
305}
306
307/* For internal use by BidiRunner. Get where the BiDi mapping for the given row
308 * needs to be stored, of nullptr if it's a context row. */
309BidiRow* RingView::get_bidirow_writable(bte::grid::row_t row) const
310{
311 if (row < m_start || row >= m_start + m_len)
312 return nullptr;
313
314 return m_bidirows[row - m_start];
315}