Fix: action error query: leak of action path
[lttng-tools.git] / src / common / actions / path.c
1 /*
2 * Copyright (C) 2021 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
8 #include <lttng/action/path-internal.h>
9
10 struct lttng_action_path_comm {
11 uint32_t index_count;
12 uint64_t indexes[];
13 } LTTNG_PACKED;
14
15 struct lttng_action_path *lttng_action_path_create(
16 const uint64_t *indexes, size_t index_count)
17 {
18 int ret;
19 size_t i;
20 struct lttng_action_path *path = NULL;
21
22 if (!indexes && index_count > 0) {
23 goto error;
24 }
25
26 path = zmalloc(sizeof(*path));
27 if (!path) {
28 goto error;
29 }
30
31 lttng_dynamic_array_init(&path->indexes, sizeof(uint64_t), NULL);
32
33 for (i = 0; i < index_count; i++) {
34 ret = lttng_dynamic_array_add_element(
35 &path->indexes, &indexes[i]);
36 if (ret) {
37 goto error;
38 }
39 }
40
41 goto end;
42 error:
43 lttng_action_path_destroy(path);
44 path = NULL;
45 end:
46 return path;
47 }
48
49 enum lttng_action_path_status lttng_action_path_get_index_count(
50 const struct lttng_action_path *path, size_t *index_count)
51 {
52 enum lttng_action_path_status status;
53
54 if (!path || !index_count) {
55 status = LTTNG_ACTION_PATH_STATUS_INVALID;
56 goto end;
57 }
58
59 *index_count = lttng_dynamic_array_get_count(&path->indexes);
60 status = LTTNG_ACTION_PATH_STATUS_OK;
61 end:
62 return status;
63 }
64
65 enum lttng_action_path_status lttng_action_path_get_index_at_index(
66 const struct lttng_action_path *path,
67 size_t path_index,
68 uint64_t *out_index)
69 {
70 enum lttng_action_path_status status;
71
72 if (!path || !out_index ||
73 path_index >= lttng_dynamic_array_get_count(
74 &path->indexes)) {
75 status = LTTNG_ACTION_PATH_STATUS_INVALID;
76 goto end;
77 }
78
79 *out_index = *((typeof(out_index)) lttng_dynamic_array_get_element(
80 &path->indexes, path_index));
81 status = LTTNG_ACTION_PATH_STATUS_OK;
82 end:
83 return status;
84 }
85
86 void lttng_action_path_destroy(struct lttng_action_path *action_path)
87 {
88 if (!action_path) {
89 goto end;
90 }
91
92 lttng_dynamic_array_reset(&action_path->indexes);
93 free(action_path);
94 end:
95 return;
96 }
97
98 LTTNG_HIDDEN
99 int lttng_action_path_copy(const struct lttng_action_path *src,
100 struct lttng_action_path **dst)
101 {
102 int ret;
103 struct lttng_action_path *new_path;
104
105 assert(src);
106 assert(dst);
107
108 new_path = lttng_action_path_create(
109 (uint64_t *) lttng_dynamic_array_get_element(
110 &src->indexes, 0),
111 lttng_dynamic_array_get_count(&src->indexes));
112 if (!new_path) {
113 ret = -1;
114 } else {
115 ret = 0;
116 *dst = new_path;
117 }
118
119 return ret;
120 }
121
122 LTTNG_HIDDEN
123 ssize_t lttng_action_path_create_from_payload(
124 struct lttng_payload_view *view,
125 struct lttng_action_path **_action_path)
126 {
127 ssize_t consumed_size = 0, ret = -1;
128 const struct lttng_action_path_comm *header;
129 struct lttng_action_path *action_path = NULL;
130 const struct lttng_payload_view header_view =
131 lttng_payload_view_from_view(view, 0, sizeof(*header));
132
133 if (!lttng_payload_view_is_valid(&header_view)) {
134 goto end;
135 }
136
137 header = (typeof(header)) header_view.buffer.data;
138 consumed_size += header_view.buffer.size;
139
140 /*
141 * An action path of size 0 can exist and represents a trigger with a
142 * single non-list action. Handle it differently since a payload view of
143 * size 0 is considered invalid.
144 */
145 if (header->index_count != 0)
146 {
147 const struct lttng_payload_view indexes_view =
148 lttng_payload_view_from_view(view,
149 consumed_size,
150 header->index_count *
151 sizeof(uint64_t));
152
153 if (!lttng_payload_view_is_valid(&indexes_view)) {
154 goto end;
155 }
156
157 consumed_size += indexes_view.buffer.size;
158 action_path = lttng_action_path_create(
159 (const uint64_t *) indexes_view.buffer.data,
160 header->index_count);
161 if (!action_path) {
162 goto end;
163 }
164 } else {
165 action_path = lttng_action_path_create(NULL, 0);
166 if (!action_path) {
167 goto end;
168 }
169 }
170
171 ret = consumed_size;
172 *_action_path = action_path;
173 end:
174 return ret;
175 }
176
177 LTTNG_HIDDEN
178 int lttng_action_path_serialize(const struct lttng_action_path *action_path,
179 struct lttng_payload *payload)
180 {
181 int ret;
182 size_t index_count, i;
183 enum lttng_action_path_status status;
184
185 status = lttng_action_path_get_index_count(action_path, &index_count);
186 if (status != LTTNG_ACTION_PATH_STATUS_OK) {
187 ret = -1;
188 goto end;
189 }
190
191 ret = lttng_dynamic_buffer_append(&payload->buffer,
192 &((struct lttng_action_path_comm) {
193 .index_count = index_count
194 }),
195 sizeof(struct lttng_action_path_comm));
196
197 for (i = 0; i < index_count; i++) {
198 uint64_t path_index;
199
200 status = lttng_action_path_get_index_at_index(
201 action_path, i, &path_index);
202 if (status != LTTNG_ACTION_PATH_STATUS_OK) {
203 ret = -1;
204 goto end;
205 }
206
207 ret = lttng_dynamic_buffer_append(&payload->buffer, &path_index,
208 sizeof(path_index));
209 if (ret) {
210 goto end;
211 }
212 }
213
214 ret = 0;
215 end:
216 return ret;
217 }
This page took 0.033348 seconds and 4 git commands to generate.