Bug Summary

File:nnc/ccv_nnc_symbolic_graph_chain_decomposition.c
Warning:line 86, 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-03-102554-588818-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
12
Loop condition is false. Execution continues on line 67
40 if (node->flags & CCV_NNC_GRAPH_EXEC_DEAD)
9
Assuming the condition is true
10
Taking true branch
41 continue;
11
Execution continues on line 39
42 int chain_id = chain_ids[idx];
43 if (chain_ids[idx] < 0)
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)
51 continue;
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.
13
Assuming the condition is true
14
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;
{
15
Loop condition is true. Entering loop body
83 buf_size = 0; /* save all its parent deps to this buffer */
84 ccv_sparse_matrix_vector_t* vector = ccv_get_sparse_matrix_vector(deps, idx);
85 if (vector)
16
Assuming 'vector' is non-null
17
Taking true branch
86 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)
;
18
Control jumps to 'case CCV_32S:' at line 86
19
Assuming the condition is true
20
Taking true branch
21
Assuming '_i_' is < field 'size'
22
Loop condition is true. Entering loop body
23
Assuming the condition is true
24
Taking true branch
25
Use of memory allocated with size zero
87 if (!node->outgoings)
88 continue;
89 const int chain_id = chain_ids[idx];
90 const int pos = chain_pos[idx];
91 for (i = 0; i < node->outgoings->rnum; i++)
92 {
93 const int outgoing = *(int*)ccv_array_get(node->outgoings, i)((void*)(((char*)((node->outgoings)->data)) + (size_t)(
node->outgoings)->rsize * (size_t)(i)))
;
94 const int outgoing_chain_id = chain_ids[outgoing];
95 if (outgoing_chain_id != chain_id)
96 {
97 ccv_numeric_data_t cell = ccv_get_sparse_matrix_cell(deps, outgoing, chain_id);
98 /* If not found, set, if the current node is the destination node, no need
99 * set itself as parent of subsequent nodes because its terminal nature. */
100 if (!cell.i32 || cell.i32[0] == 0 || cell.i32[0] < pos)
101 {
102 int p[2] = { pos, 1 };
103 ccv_set_sparse_matrix_cell(deps, outgoing, chain_id, &p);
104 }
105 }
106 if (buf_size > 0)
107 {
108 ccv_sparse_matrix_vector_t* vector = ccv_get_sparse_matrix_vector(deps, outgoing);
109 for (j = 0; j < buf_size; j++) /* set with all idx's dependencies as well */
110 {
111 if (outgoing_chain_id == buf[j * 3]) // We don't need to add as dependency for the same chain.
112 continue;
113 if (!vector)
114 {
115 ccv_set_sparse_matrix_cell(deps, outgoing, buf[j * 3], &buf[j * 3 + 1]);
116 vector = ccv_get_sparse_matrix_vector(deps, outgoing);
117 continue;
118 }
119 ccv_numeric_data_t cell = ccv_get_sparse_matrix_cell_from_vector(deps, vector, buf[j * 3]);
120 /* If not found, set. Otherwise, set to the latest one only if it is later. */
121 if (!cell.i32)
122 ccv_set_sparse_matrix_cell_from_vector(deps, vector, buf[j * 3], &buf[j * 3 + 1]);
123 else if (cell.i32[0] == 0 || cell.i32[0] < buf[j * 3 + 1])
124 ccv_set_sparse_matrix_cell_from_vector(deps, vector, buf[j * 3], &buf[j * 3 + 1]);
125 else if (cell.i32[0] == buf[j * 3 + 1]) { // If we point to the same one, use the longest.
126 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; })
};
127 ccv_set_sparse_matrix_cell_from_vector(deps, vector, buf[j * 3], &p);
128 }
129 }
130 }
131 }
132 } ccv_nnc_graph_visit_endfor} }
133#undef for_block
134 ccfreefree(buf);
135 ccv_nnc_exec_dep_t exec_dep = {
136 .chain_ids = chain_ids,
137 .chain_pos = chain_pos,
138 .deps = deps
139 };
140 return exec_dep;
141}
142
143void ccv_nnc_exec_dep_free(const ccv_nnc_exec_dep_t exec_dep)
144{
145 ccfreefree(exec_dep.chain_ids);
146 ccv_matrix_free(exec_dep.deps);
147}