Bug Summary

File:nnc/ccv_nnc_symbolic_graph_chain_decomposition.c
Warning:line 88, column 4
Use of memory allocated with size zero

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ccv_nnc_symbolic_graph_chain_decomposition.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -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 -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +sse2 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/home/liu/actions-runner/_work/ccv/ccv/lib/nnc -fcoverage-compilation-dir=/home/liu/actions-runner/_work/ccv/ccv/lib/nnc -resource-dir /usr/local/lib/clang/19 -I ../ -I /usr/local/cuda/include -D HAVE_CBLAS -D HAVE_LIBPNG -D HAVE_LIBJPEG -D HAVE_FFTW3 -D HAVE_PTHREAD -D HAVE_LIBLINEAR -D HAVE_TESSERACT -D HAVE_AVCODEC -D HAVE_AVFORMAT -D HAVE_AVUTIL -D HAVE_SWSCALE -D HAVE_SSE2 -D HAVE_GSL -D HAVE_CUDA -D HAVE_CUDNN -D HAVE_NCCL -D USE_SYSTEM_CUB -I /usr/local/include -internal-isystem /usr/local/lib/clang/19/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 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/liu/actions-runner/_work/ccv/ccv/_analyze/2024-12-10-173524-342268-1 -x c ccv_nnc_symbolic_graph_chain_decomposition.c
1#include "ccv_nnc.h"
2#include "ccv_nnc_easy.h"
3#include "ccv_nnc_internal.h"
4#include "ccv_internal.h"
5#include "_ccv_nnc_symbolic_graph.h"
6
7// Implement the new method for exec_dep. We use chain decomposition such that each node only needs to log which chain and at which node to be dependent on.
8ccv_nnc_exec_dep_t ccv_nnc_exec_dep_new(const ccv_nnc_symbolic_graph_t* const graph, const ccv_nnc_graph_visit_t* const visit)
9{
10 const int exec_symbol_info_size = graph->exec_symbol_info->rnum;
11 int* chain_ids = ccmallocmalloc(sizeof(int) * exec_symbol_info_size * 2);
12 int* chain_pos = chain_ids + exec_symbol_info_size;
13 int* buf = (int*)ccmallocmalloc(sizeof(int) * exec_symbol_info_size);
14 int* reversed_depth = buf;
15 const ccv_nnc_graph_exec_symbol_info_t* const exec_symbol_info = (ccv_nnc_graph_exec_symbol_info_t*)ccv_array_get(graph->exec_symbol_info, 0)((void*)(((char*)((graph->exec_symbol_info)->data)) + (
size_t)(graph->exec_symbol_info)->rsize * (size_t)(0)))
;
16 int i, j;
17 // Go reverse order to generate the distance from sink.
18 ccv_nnc_graph_visit_for_reversed(visit, exec_symbol_info, node, idx, term){ int _i_; for (_i_ = (visit)->size - 1; _i_ >= 0; _i_--
) { const int idx __attribute__((unused)) = (visit)->node[
_i_].index; const int term __attribute__((unused)) = (visit)->
node[_i_].term; typeof ((exec_symbol_info)) const node __attribute__
((unused)) = (exec_symbol_info) + idx;
{
1
Assuming '_i_' is >= 0
2
Loop condition is true. Entering loop body
6
Assuming '_i_' is < 0
7
Loop condition is false. Execution continues on line 38
19 if (node->flags & CCV_NNC_GRAPH_EXEC_DEAD)
3
Assuming the condition is true
4
Taking true branch
20 continue;
5
Execution continues on line 18
21 chain_ids[idx] = -1;
22 if (!node->outgoings || node->outgoings->rnum == 0)
23 {
24 reversed_depth[idx] = 0;
25 continue;
26 }
27 const int outgoing = *(int*)ccv_array_get(node->outgoings, 0)((void*)(((char*)((node->outgoings)->data)) + (size_t)(
node->outgoings)->rsize * (size_t)(0)))
;
28 int depth = reversed_depth[outgoing];
29 for (i = 1; i < node->outgoings->rnum; i++)
30 {
31 const int outgoing = *(int*)ccv_array_get(node->outgoings, i)((void*)(((char*)((node->outgoings)->data)) + (size_t)(
node->outgoings)->rsize * (size_t)(i)))
;
32 depth = ccv_max(depth, reversed_depth[outgoing])({ typeof (depth) _a = (depth); typeof (reversed_depth[outgoing
]) _b = (reversed_depth[outgoing]); (_a > _b) ? _a : _b; }
)
;
33 }
34 reversed_depth[idx] = depth + 1;
35 } ccv_nnc_graph_visit_endfor} }
36 // Go in order to generate chain ids (if there are multiple exits, we use the reverse depth to break the tie).
37 // Note that we cannot use depth so-far because then multiple exit nodes are equally good to "inherit" the chain selection.
38 int chain_count = 0;
39 ccv_nnc_graph_visit_for(visit, exec_symbol_info, node, idx, term){ int _i_; for (_i_ = 0; _i_ < (visit)->size; _i_++) { const
int idx __attribute__((unused)) = (visit)->node[_i_].index
; const int term __attribute__((unused)) = (visit)->node[_i_
].term; typeof ((exec_symbol_info)) const node __attribute__(
(unused)) = (exec_symbol_info) + idx;
{
8
Loop condition is true. Entering loop body
14
Loop condition is false. Execution continues on line 67
40 if (node->flags & CCV_NNC_GRAPH_EXEC_DEAD)
9
Assuming the condition is false
10
Taking false branch
41 continue;
42 int chain_id = chain_ids[idx];
43 if (chain_ids[idx] < 0)
11
Assuming the condition is false
44 {
45 chain_id = chain_count;
46 chain_ids[idx] = chain_id;
47 chain_pos[idx] = 1; // The first one in this chain. 1-based index because in sparse matrix, 0 is the default value.
48 chain_count += 1;
49 }
50 if (!node->outgoings || node->outgoings->rnum == 0)
12
Assuming field 'outgoings' is null
51 continue;
13
Execution continues on line 39
52 int depth = -1;
53 int next_idx = -1;
54 for (i = 0; i < node->outgoings->rnum; i++)
55 {
56 const int outgoing = *(int*)ccv_array_get(node->outgoings, i)((void*)(((char*)((node->outgoings)->data)) + (size_t)(
node->outgoings)->rsize * (size_t)(i)))
;
57 if (chain_ids[outgoing] < 0 && reversed_depth[outgoing] > depth)
58 depth = reversed_depth[outgoing], next_idx = outgoing;
59 }
60 if (next_idx >= 0)
61 {
62 chain_ids[next_idx] = chain_id;
63 assert(reversed_depth[idx] - depth >= 1)((void) sizeof ((reversed_depth[idx] - depth >= 1) ? 1 : 0
), __extension__ ({ if (reversed_depth[idx] - depth >= 1) ;
else __assert_fail ("reversed_depth[idx] - depth >= 1", "ccv_nnc_symbolic_graph_chain_decomposition.c"
, 63, __extension__ __PRETTY_FUNCTION__); }))
;
64 chain_pos[next_idx] = chain_pos[idx] + (reversed_depth[idx] - depth);
65 }
66 } ccv_nnc_graph_visit_endfor} }
67 if (exec_symbol_info_size < chain_count * 3) // Be more conservative on RAM usage.
15
Assuming the condition is true
16
Taking true branch
68 buf = ccreallocrealloc(buf, sizeof(int) * chain_count * 3);
69 ccv_sparse_matrix_t* deps = ccv_sparse_matrix_new(graph->exec_symbol_info->rnum, chain_count, CCV_32S | CCV_C2, CCV_SPARSE_ROW_MAJOR, 0);
70 // It logs which pos on that chain we depend on. We can simply compare that with the chain_pos for a node to know if they are ancestors.
71#define for_block(x, val) \
72 do { \
73 if (((int32_t*)val)[0] > 0) \
74 { \
75 buf[buf_size * 3] = x; \
76 buf[buf_size * 3 + 1] = ((int32_t*)val)[0]; \
77 buf[buf_size * 3 + 2] = ((int32_t*)val)[1] + 1; \
78 ++buf_size; \
79 } \
80 } while (0)
81 int buf_size;
82 ccv_nnc_graph_visit_for(visit, exec_symbol_info, node, idx, term){ int _i_; for (_i_ = 0; _i_ < (visit)->size; _i_++) { const
int idx __attribute__((unused)) = (visit)->node[_i_].index
; const int term __attribute__((unused)) = (visit)->node[_i_
].term; typeof ((exec_symbol_info)) const node __attribute__(
(unused)) = (exec_symbol_info) + idx;
{
17
Loop condition is true. Entering loop body
83 if (node->flags & CCV_NNC_GRAPH_EXEC_DEAD)
18
Taking false branch
84 continue;
85 buf_size = 0; /* save all its parent deps to this buffer */
86 ccv_sparse_matrix_vector_t* vector = ccv_get_sparse_matrix_vector(deps, idx);
87 if (vector)
19
Assuming 'vector' is non-null
20
Taking true branch
88 CCV_SPARSE_VECTOR_FOREACH(deps, vector, for_block)do { switch ((((deps)->type) & 0xFF000)) { case CCV_32S
: { do { int _i_; __attribute__((unused)) const size_t _c_ = (
((deps)->type) & 0xFFF); if ((deps)->type & CCV_DENSE_VECTOR
) { for (_i_ = 0; _i_ < (vector)->size; _i_++) { for_block
((_i_), ((vector)->data.i32 + (_i_ * _c_))); } } else { const
size_t _idx_size_ = sizeof(ccv_sparse_matrix_index_t) + ((_ccv_get_data_type_size
[(((deps)->type) & 0xFF000) >> 12] * (((deps)->
type) & 0xFFF) + 3) & -4); uint8_t* const _vidx_ = (uint8_t
*)(vector)->index; for (_i_ = 0; _i_ < (vector)->size
; _i_++) { ccv_sparse_matrix_index_t* const _idx_i_ = (ccv_sparse_matrix_index_t
*)(_vidx_ + _idx_size_ * _i_); if (_idx_i_->ifbit <= 1)
continue; ccv_numeric_data_t _d_ = { .u8 = (uint8_t*)(_idx_i_
+ 1) }; for_block((_idx_i_->i), (_d_.i32 + (0))); } } } while
(0); break; } case CCV_32F: { do { int _i_; __attribute__((unused
)) const size_t _c_ = (((deps)->type) & 0xFFF); if ((deps
)->type & CCV_DENSE_VECTOR) { for (_i_ = 0; _i_ < (
vector)->size; _i_++) { for_block((_i_), ((vector)->data
.f32 + (_i_ * _c_))); } } else { const size_t _idx_size_ = sizeof
(ccv_sparse_matrix_index_t) + ((_ccv_get_data_type_size[(((deps
)->type) & 0xFF000) >> 12] * (((deps)->type) &
0xFFF) + 3) & -4); uint8_t* const _vidx_ = (uint8_t*)(vector
)->index; for (_i_ = 0; _i_ < (vector)->size; _i_++)
{ ccv_sparse_matrix_index_t* const _idx_i_ = (ccv_sparse_matrix_index_t
*)(_vidx_ + _idx_size_ * _i_); if (_idx_i_->ifbit <= 1)
continue; ccv_numeric_data_t _d_ = { .u8 = (uint8_t*)(_idx_i_
+ 1) }; for_block((_idx_i_->i), (_d_.f32 + (0))); } } } while
(0); break; } case CCV_64S: { do { int _i_; __attribute__((unused
)) const size_t _c_ = (((deps)->type) & 0xFFF); if ((deps
)->type & CCV_DENSE_VECTOR) { for (_i_ = 0; _i_ < (
vector)->size; _i_++) { for_block((_i_), ((vector)->data
.i64 + (_i_ * _c_))); } } else { const size_t _idx_size_ = sizeof
(ccv_sparse_matrix_index_t) + ((_ccv_get_data_type_size[(((deps
)->type) & 0xFF000) >> 12] * (((deps)->type) &
0xFFF) + 3) & -4); uint8_t* const _vidx_ = (uint8_t*)(vector
)->index; for (_i_ = 0; _i_ < (vector)->size; _i_++)
{ ccv_sparse_matrix_index_t* const _idx_i_ = (ccv_sparse_matrix_index_t
*)(_vidx_ + _idx_size_ * _i_); if (_idx_i_->ifbit <= 1)
continue; ccv_numeric_data_t _d_ = { .u8 = (uint8_t*)(_idx_i_
+ 1) }; for_block((_idx_i_->i), (_d_.i64 + (0))); } } } while
(0); break; } case CCV_64F: { do { int _i_; __attribute__((unused
)) const size_t _c_ = (((deps)->type) & 0xFFF); if ((deps
)->type & CCV_DENSE_VECTOR) { for (_i_ = 0; _i_ < (
vector)->size; _i_++) { for_block((_i_), ((vector)->data
.f64 + (_i_ * _c_))); } } else { const size_t _idx_size_ = sizeof
(ccv_sparse_matrix_index_t) + ((_ccv_get_data_type_size[(((deps
)->type) & 0xFF000) >> 12] * (((deps)->type) &
0xFFF) + 3) & -4); uint8_t* const _vidx_ = (uint8_t*)(vector
)->index; for (_i_ = 0; _i_ < (vector)->size; _i_++)
{ ccv_sparse_matrix_index_t* const _idx_i_ = (ccv_sparse_matrix_index_t
*)(_vidx_ + _idx_size_ * _i_); if (_idx_i_->ifbit <= 1)
continue; ccv_numeric_data_t _d_ = { .u8 = (uint8_t*)(_idx_i_
+ 1) }; for_block((_idx_i_->i), (_d_.f64 + (0))); } } } while
(0); break; } default: { do { int _i_; __attribute__((unused
)) const size_t _c_ = (((deps)->type) & 0xFFF); if ((deps
)->type & CCV_DENSE_VECTOR) { for (_i_ = 0; _i_ < (
vector)->size; _i_++) { for_block((_i_), ((vector)->data
.u8 + (_i_ * _c_))); } } else { const size_t _idx_size_ = sizeof
(ccv_sparse_matrix_index_t) + ((_ccv_get_data_type_size[(((deps
)->type) & 0xFF000) >> 12] * (((deps)->type) &
0xFFF) + 3) & -4); uint8_t* const _vidx_ = (uint8_t*)(vector
)->index; for (_i_ = 0; _i_ < (vector)->size; _i_++)
{ ccv_sparse_matrix_index_t* const _idx_i_ = (ccv_sparse_matrix_index_t
*)(_vidx_ + _idx_size_ * _i_); if (_idx_i_->ifbit <= 1)
continue; ccv_numeric_data_t _d_ = { .u8 = (uint8_t*)(_idx_i_
+ 1) }; for_block((_idx_i_->i), (_d_.u8 + (0))); } } } while
(0); } } } while (0)
;
21
Control jumps to 'case CCV_32S:' at line 88
22
Assuming the condition is true
23
Taking true branch
24
Assuming '_i_' is < field 'size'
25
Loop condition is true. Entering loop body
26
Assuming the condition is true
27
Taking true branch
28
Use of memory allocated with size zero
89 if (!node->outgoings)
90 continue;
91 const int chain_id = chain_ids[idx];
92 const int pos = chain_pos[idx];
93 for (i = 0; i < node->outgoings->rnum; i++)
94 {
95 const int outgoing = *(int*)ccv_array_get(node->outgoings, i)((void*)(((char*)((node->outgoings)->data)) + (size_t)(
node->outgoings)->rsize * (size_t)(i)))
;
96 const int outgoing_chain_id = chain_ids[outgoing];
97 if (outgoing_chain_id != chain_id)
98 {
99 ccv_numeric_data_t cell = ccv_get_sparse_matrix_cell(deps, outgoing, chain_id);
100 /* If not found, set, if the current node is the destination node, no need
101 * set itself as parent of subsequent nodes because its terminal nature. */
102 if (!cell.i32 || cell.i32[0] == 0 || cell.i32[0] < pos)
103 {
104 int p[2] = { pos, 1 };
105 ccv_set_sparse_matrix_cell(deps, outgoing, chain_id, &p);
106 }
107 }
108 if (buf_size > 0)
109 {
110 ccv_sparse_matrix_vector_t* vector = ccv_get_sparse_matrix_vector(deps, outgoing);
111 for (j = 0; j < buf_size; j++) /* set with all idx's dependencies as well */
112 {
113 if (outgoing_chain_id == buf[j * 3]) // We don't need to add as dependency for the same chain.
114 continue;
115 if (!vector)
116 {
117 ccv_set_sparse_matrix_cell(deps, outgoing, buf[j * 3], &buf[j * 3 + 1]);
118 vector = ccv_get_sparse_matrix_vector(deps, outgoing);
119 continue;
120 }
121 ccv_numeric_data_t cell = ccv_get_sparse_matrix_cell_from_vector(deps, vector, buf[j * 3]);
122 /* If not found, set. Otherwise, set to the latest one only if it is later. */
123 if (!cell.i32)
124 ccv_set_sparse_matrix_cell_from_vector(deps, vector, buf[j * 3], &buf[j * 3 + 1]);
125 else if (cell.i32[0] == 0 || cell.i32[0] < buf[j * 3 + 1])
126 ccv_set_sparse_matrix_cell_from_vector(deps, vector, buf[j * 3], &buf[j * 3 + 1]);
127 else if (cell.i32[0] == buf[j * 3 + 1]) { // If we point to the same one, use the longest.
128 int p[2] = { cell.i32[0], ccv_max(buf[j * 3 + 2], cell.i32[1])({ typeof (buf[j * 3 + 2]) _a = (buf[j * 3 + 2]); typeof (cell
.i32[1]) _b = (cell.i32[1]); (_a > _b) ? _a : _b; })
};
129 ccv_set_sparse_matrix_cell_from_vector(deps, vector, buf[j * 3], &p);
130 }
131 }
132 }
133 }
134 } ccv_nnc_graph_visit_endfor} }
135#undef for_block
136 ccfreefree(buf);
137 ccv_nnc_exec_dep_t exec_dep = {
138 .chain_ids = chain_ids,
139 .chain_pos = chain_pos,
140 .deps = deps
141 };
142 return exec_dep;
143}
144
145void ccv_nnc_exec_dep_free(const ccv_nnc_exec_dep_t exec_dep)
146{
147 ccfreefree(exec_dep.chain_ids);
148 ccv_matrix_free(exec_dep.deps);
149}