1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "rbtree.h"
17
18 #include "securec.h"
19
20 #include "cert_manager_mem.h"
21 #include "cm_log.h"
22
23 /* void orintRbTree(struct RbTree *t)
24 Implementation of a red-black tree, with serialization
25 Reference: Introduction to Algortihms, 3ed edition
26 thr following assume each key is a 31-bit integer (uint32_t), adjust if nedded */
27 #define COLOR_MASK 0x80000000
28 #define KEY_MASK 0x7fffffff
29 #define BLACK 0x80000000
30 #define RED 0
31
32 #define COLOR(n) ((n) == NULL ? BLACK : ((n)->key & COLOR_MASK))
33 #define IS_RED(n) (COLOR((n)) == RED)
34 #define IS_BLACK(n) (COLOR((n)) == BLACK)
35
36 #define SET_COLOR(n, color) if ((n) != NULL) { (n)->key = ((n)->key & KEY_MASK) | (color); }
37 #define SET_RED(n) SET_COLOR((n), RED)
38 #define SET_BLACK(n) SET_COLOR((n), BLACK)
39
40 #define KEY(n) ((n) == NULL ? RED : ((n)->key & KEY_MASK))
41
42 #ifdef __cplusplus
43 extern "C" {
44 #endif
45
46 struct EncoderContext {
47 uint8_t *buf;
48 uint32_t off;
49 uint32_t len;
50 int32_t status;
51 RbTreeValueEncoder enc;
52 };
53
54 // LCOV_EXCL_START
RbTreeNodeKey(const struct RbTreeNode * n)55 RbTreeKey RbTreeNodeKey(const struct RbTreeNode *n)
56 {
57 return n == NULL ? 0 : KEY(n);
58 }
59
NewNode(struct RbTreeNode ** nptr,RbTreeKey key,RbTreeValue value)60 static int32_t NewNode(struct RbTreeNode **nptr, RbTreeKey key, RbTreeValue value)
61 {
62 struct RbTreeNode *n = CMMalloc(sizeof(struct RbTreeNode));
63 if (n == NULL) {
64 return CMR_ERROR_MALLOC_FAIL;
65 }
66 *nptr = n;
67 n->key = key;
68 n->value = value;
69 n->p = NULL;
70 n->left = NULL;
71 n->right = NULL;
72 return CM_SUCCESS;
73 }
74
RbTreeNew(struct RbTree * t)75 int32_t RbTreeNew(struct RbTree *t)
76 {
77 if (t == NULL) {
78 CM_LOG_E("input param is invaild");
79 return CM_FAILURE;
80 }
81
82 int32_t ret = NewNode(&(t->nil), 0, NULL);
83 if (ret != CM_SUCCESS) {
84 CM_LOG_E("create new code failed");
85 return ret;
86 }
87 SET_BLACK(t->nil);
88 t->root = t->nil;
89
90 return ret;
91 }
92
LeftRotate(struct RbTree * t,struct RbTreeNode * x)93 static void LeftRotate(struct RbTree *t, struct RbTreeNode *x)
94 {
95 struct RbTreeNode *y = x->right;
96 x->right = y->left;
97 if (y->left != t->nil) {
98 y->left->p = x;
99 }
100 y->p = x->p;
101 if (x->p == t->nil) {
102 t->root = y;
103 } else if (x == x->p->left) {
104 x->p->left = y;
105 } else {
106 x->p->right = y;
107 }
108 y->left = x;
109 x->p = y;
110 }
111
RightRotate(struct RbTree * t,struct RbTreeNode * x)112 static void RightRotate(struct RbTree *t, struct RbTreeNode *x)
113 {
114 struct RbTreeNode *y = x->left;
115 x->left = y->right;
116 if (y->right != t->nil) {
117 y->right->p = x;
118 }
119 y->p = x->p;
120 if (x->p == t->nil) {
121 t->root = y;
122 } else if (x == x->p->right) {
123 x->p->right = y;
124 } else {
125 x->p->left = y;
126 }
127 y->right = x;
128 x->p = y;
129 }
130
InsertFixUpRed(struct RbTree * t,struct RbTreeNode ** zTreeNode)131 static void InsertFixUpRed(struct RbTree *t, struct RbTreeNode **zTreeNode)
132 {
133 struct RbTreeNode *y = NULL;
134 struct RbTreeNode *z = *zTreeNode;
135 y = z->p->p->right;
136 if (IS_RED(y)) {
137 SET_BLACK(z->p);
138 SET_BLACK(y);
139 SET_RED(z->p->p);
140 z = z->p->p;
141 } else {
142 if (z == z->p->right) {
143 z = z->p;
144 LeftRotate(t, z);
145 }
146 // case 3
147 SET_BLACK(z->p);
148 SET_RED(z->p->p);
149 RightRotate(t, z->p->p);
150 }
151 *zTreeNode = z;
152 }
153
InsertFixUpBlack(struct RbTree * t,struct RbTreeNode ** zTreeNode)154 static void InsertFixUpBlack(struct RbTree *t, struct RbTreeNode **zTreeNode)
155 {
156 struct RbTreeNode *y = NULL;
157 struct RbTreeNode *z = *zTreeNode;
158
159 y = z->p->p->left;
160 if (IS_RED(y)) {
161 SET_BLACK(z->p);
162 SET_BLACK(y);
163 SET_RED(z->p->p);
164 z = z->p->p;
165 } else {
166 if (z == z->p->left) {
167 z = z->p;
168 RightRotate(t, z);
169 }
170 SET_BLACK(z->p);
171 SET_RED(z->p->p);
172 LeftRotate(t, z->p->p);
173 }
174 *zTreeNode = z;
175 }
176
InsertFixUp(struct RbTree * t,struct RbTreeNode * z)177 static void InsertFixUp(struct RbTree *t, struct RbTreeNode *z)
178 {
179 while (IS_RED(z->p)) {
180 if (z->p == z->p->p->left) {
181 InsertFixUpRed(t, &z);
182 } else {
183 InsertFixUpBlack(t, &z);
184 }
185 }
186
187 SET_BLACK(t->root);
188 }
189
RbTreeInsert(struct RbTree * t,RbTreeKey key,const RbTreeValue value)190 int32_t RbTreeInsert(struct RbTree *t, RbTreeKey key, const RbTreeValue value)
191 {
192 if (t == NULL) {
193 CM_LOG_E("input param is invaild");
194 return CM_FAILURE;
195 }
196
197 struct RbTreeNode *z = NULL;
198 int32_t ret = NewNode(&z, key, value);
199 if (ret != CM_SUCCESS) {
200 CM_LOG_E("create new code failed");
201 return ret;
202 }
203
204 struct RbTreeNode *y = t->nil;
205 struct RbTreeNode *x = t->root;
206
207 while (x != t->nil) {
208 y = x;
209 if (KEY(z) < KEY(x)) {
210 x = x->left;
211 } else {
212 x = x->right;
213 }
214 }
215
216 z->p = y;
217 if (y == t->nil) {
218 t->root = z;
219 } else if (KEY(z) < KEY(y)) {
220 y->left = z;
221 } else {
222 y->right = z;
223 }
224
225 z->left = t->nil;
226 z->right = t->nil;
227 SET_RED(z);
228
229 InsertFixUp(t, z);
230
231 return ret;
232 }
233
Transplant(struct RbTree * t,struct RbTreeNode * u,struct RbTreeNode * v)234 static void Transplant(struct RbTree *t, struct RbTreeNode *u, struct RbTreeNode *v)
235 {
236 if (u->p == t->nil) {
237 t->root = v;
238 } else if (u == u->p->left) {
239 u->p->left = v;
240 } else {
241 u->p->right = v;
242 }
243 if (v != NULL) {
244 v->p = u->p;
245 }
246 }
247
Minimum(const struct RbTree * t,struct RbTreeNode * x)248 static struct RbTreeNode *Minimum(const struct RbTree *t, struct RbTreeNode *x)
249 {
250 while (x->left != t->nil) {
251 x = x->left;
252 }
253 return x;
254 }
255
DeleteFixUpBlack(struct RbTree * t,struct RbTreeNode ** treeNode)256 static void DeleteFixUpBlack(struct RbTree *t, struct RbTreeNode **treeNode)
257 {
258 struct RbTreeNode *w = NULL;
259 struct RbTreeNode *x = *treeNode;
260 w = x->p->right;
261 if (IS_RED(w)) {
262 SET_BLACK(w);
263 SET_RED(x->p);
264 LeftRotate(t, x->p);
265 w = x->p->right;
266 }
267 if (IS_BLACK(w->left) && IS_BLACK(w->right)) {
268 SET_RED(w);
269 x = x->p;
270 } else {
271 if (IS_BLACK(w->right)) {
272 SET_BLACK(w->left);
273 SET_RED(w);
274 RightRotate(t, w);
275 w = x->p->right;
276 }
277
278 SET_COLOR(w, COLOR(x->p));
279 SET_BLACK(x->p);
280 SET_BLACK(w->right);
281 LeftRotate(t, x->p);
282 x = t->root;
283 }
284 *treeNode = x;
285 }
286
DeleteFixUpRed(struct RbTree * t,struct RbTreeNode ** treeNode)287 static void DeleteFixUpRed(struct RbTree *t, struct RbTreeNode **treeNode)
288 {
289 struct RbTreeNode *w = NULL;
290 struct RbTreeNode *x = *treeNode;
291
292 w = x->p->left;
293 if (IS_RED(w)) {
294 SET_BLACK(w);
295 SET_RED(x->p);
296 RightRotate(t, x->p);
297 w = x->p->left;
298 }
299 if (IS_BLACK(w->right) && IS_BLACK(w->left)) {
300 SET_RED(w);
301 x = x->p;
302 } else {
303 if (IS_BLACK(w->left)) {
304 SET_BLACK(w->right);
305 SET_RED(w);
306 LeftRotate(t, w);
307 w = x->p->left;
308 }
309
310 SET_COLOR(w, COLOR(x->p));
311 SET_BLACK(x->p);
312 SET_BLACK(w->left);
313 RightRotate(t, x->p);
314 x = t->root;
315 }
316 *treeNode = x;
317 }
318
DeleteFixUp(struct RbTree * t,struct RbTreeNode * x)319 static void DeleteFixUp(struct RbTree *t, struct RbTreeNode *x)
320 {
321 while (x != t->root && IS_BLACK(x)) {
322 if (x == x->p->left) {
323 DeleteFixUpBlack(t, &x);
324 } else {
325 DeleteFixUpRed(t, &x);
326 }
327 }
328 SET_BLACK(x);
329 }
330
RbTreeDelete(struct RbTree * t,struct RbTreeNode * z)331 int32_t RbTreeDelete(struct RbTree *t, struct RbTreeNode *z)
332 {
333 if (t == NULL) {
334 CM_LOG_E("input param is invaild");
335 return CM_FAILURE;
336 }
337 struct RbTreeNode *x = NULL;
338 struct RbTreeNode *y = z;
339 RbTreeKey yColor = COLOR(y);
340
341 if (z->left == t->nil) {
342 x = z->right;
343 Transplant(t, z, z->right);
344 } else if (z->right == t->nil) {
345 x = z->left;
346 Transplant(t, z, z->left);
347 } else {
348 y = Minimum(t, z->right);
349 yColor = COLOR(y);
350 x = y->right;
351 if (y->p == z) {
352 x->p = y;
353 } else {
354 Transplant(t, y, y->right);
355 y->right = z->right;
356 if (y->right != NULL) {
357 y->right->p = y;
358 }
359 }
360 Transplant(t, z, y);
361 y->left = z->left;
362 if (y->left != NULL) {
363 y->left->p = y;
364 }
365 SET_COLOR(y, COLOR(z));
366 }
367 if (yColor == BLACK) {
368 DeleteFixUp(t, x);
369 }
370 CMFree(z);
371 return CM_SUCCESS;
372 }
373
RbTreeFindNode(struct RbTreeNode ** nodePtr,RbTreeKey key,const struct RbTree * tree)374 int32_t RbTreeFindNode(struct RbTreeNode **nodePtr, RbTreeKey key, const struct RbTree *tree)
375 {
376 if (tree == NULL || nodePtr == NULL) {
377 CM_LOG_E("input param is invaild");
378 return CM_FAILURE;
379 }
380
381 *nodePtr = NULL;
382
383 struct RbTreeNode *n = tree->root;
384 while (n != tree->nil) {
385 if (KEY(n) == key) {
386 *nodePtr = n;
387 return CM_SUCCESS;
388 } else if (key < KEY(n)) {
389 n = n->left;
390 } else {
391 n = n->right;
392 }
393 }
394 return CMR_ERROR_NOT_FOUND;
395 }
396
TraverseInOrder(const struct RbTree * t,const struct RbTreeNode * x,RbTreeNodeHandler handler,const void * context)397 static void TraverseInOrder(const struct RbTree *t, const struct RbTreeNode *x,
398 RbTreeNodeHandler handler, const void *context)
399 {
400 if (x == t->nil) {
401 return;
402 }
403 TraverseInOrder(t, x->left, handler, context);
404 handler(KEY(x), x->value, context);
405 TraverseInOrder(t, x->right, handler, context);
406 }
407
TraversePreOrder(const struct RbTree * t,const struct RbTreeNode * x,RbTreeNodeHandler handler,const void * context)408 static void TraversePreOrder(const struct RbTree *t, const struct RbTreeNode *x,
409 RbTreeNodeHandler handler, const void *context)
410 {
411 if (x == t->nil) {
412 return;
413 }
414 handler(KEY(x), x->value, context);
415 TraversePreOrder(t, x->left, handler, context);
416 TraversePreOrder(t, x->right, handler, context);
417 }
418
TraversePostOrder(const struct RbTree * t,const struct RbTreeNode * x,RbTreeNodeHandler handler,const void * context)419 static void TraversePostOrder(const struct RbTree *t, const struct RbTreeNode *x,
420 RbTreeNodeHandler handler, const void *context)
421 {
422 if (x == t->nil) {
423 return;
424 }
425 TraversePostOrder(t, x->left, handler, context);
426 TraversePostOrder(t, x->right, handler, context);
427 handler(KEY(x), x->value, context);
428 }
429
Encoder(RbTreeKey key,RbTreeValue value,const void * context)430 static void Encoder(RbTreeKey key, RbTreeValue value, const void *context)
431 {
432 struct EncoderContext *ctx = (struct EncoderContext *)context;
433 if (ctx->status != CM_SUCCESS) {
434 CM_LOG_E("already failed: %d", ctx->status); /* already failed. do not continue */
435 return;
436 }
437
438 uint32_t valueSize = 0;
439 int rc = ctx->enc(value, NULL, &valueSize); /* get value size */
440 if (rc != CM_SUCCESS) {
441 CM_LOG_E("value encoder get length failed: %d", rc);
442 ctx->status = rc;
443 return;
444 }
445
446 uint32_t keySize = sizeof(RbTreeKey);
447 if (valueSize > (UINT32_MAX - keySize - sizeof(uint32_t))) {
448 ctx->status = CMR_ERROR_INVALID_ARGUMENT;
449 return;
450 }
451
452 /* each code is encoded ad (key | encoded_value_len | encoded_value)
453 encoded_value_len is uint32_t. */
454 uint32_t sz = keySize + sizeof(uint32_t) + valueSize;
455 if (sz > (UINT32_MAX - ctx->off)) {
456 ctx->status = CMR_ERROR_INVALID_ARGUMENT;
457 return;
458 }
459
460 /* if buffer is provided, do the actual encoding */
461 if (ctx->buf != NULL) {
462 if (ctx->off + sz > ctx->len) {
463 ctx->status = CMR_ERROR_BUFFER_TOO_SMALL;
464 return;
465 }
466 uint8_t *buf = ctx->buf + ctx->off;
467 if (memcpy_s(buf, ctx->len - ctx->off, &key, keySize) != EOK) {
468 ctx->status = CMR_ERROR_INVALID_ARGUMENT;
469 return;
470 }
471 buf += keySize;
472 if (memcpy_s(buf, ctx->len - ctx->off - keySize, &valueSize, sizeof(uint32_t)) != EOK) {
473 ctx->status = CMR_ERROR_INVALID_ARGUMENT;
474 return;
475 }
476 buf += sizeof(uint32_t);
477 rc = ctx->enc(value, buf, &valueSize);
478 if (rc != CM_SUCCESS) {
479 CM_LOG_E("value encoder encoding failed: %d", rc);
480 ctx->status = rc;
481 return;
482 }
483 }
484 /* in any case, updata offset in context. */
485 ctx->off += sz;
486 }
487
RbTreeEncode(const struct RbTree * t,RbTreeValueEncoder enc,uint8_t * buf,uint32_t * size)488 int32_t RbTreeEncode(const struct RbTree *t, RbTreeValueEncoder enc, uint8_t *buf, uint32_t *size)
489 {
490 if (t == NULL || t->root == NULL || enc == NULL || size == NULL) {
491 CM_LOG_E("input param is invaild");
492 return CM_FAILURE;
493 }
494
495 struct EncoderContext ctx = {
496 .buf = buf,
497 .off = 0,
498 .len = *size,
499 .status = CM_SUCCESS,
500 .enc = enc,
501 };
502
503 TraverseInOrder(t, t->root, Encoder, &ctx);
504 if (ctx.status != CM_SUCCESS) {
505 return ctx.status;
506 }
507 *size = ctx.off;
508 return CM_SUCCESS;
509 }
510
RbTreeDecode(struct RbTree * t,RbTreeValueDecoder dec,RbTreeValueFree freeFunc,uint8_t * buf,uint32_t size)511 int32_t RbTreeDecode(struct RbTree *t, RbTreeValueDecoder dec, RbTreeValueFree freeFunc,
512 uint8_t *buf, uint32_t size)
513 {
514 if (t == NULL || t->root == NULL || dec == NULL || freeFunc == NULL || buf == NULL || size == 0) {
515 CM_LOG_E("input param is invaild");
516 return CM_FAILURE;
517 }
518
519 uint32_t off = 0;
520 while (off < size) {
521 uint32_t remaining = size - off;
522 uint32_t headerSize = sizeof(RbTreeKey) + sizeof(uint32_t);
523
524 if (remaining < headerSize) {
525 /* something is wrong */
526 return CMR_ERROR_BUFFER_TOO_SMALL;
527 }
528
529 uint8_t *s = buf + off;
530
531 RbTreeKey key;
532 if (memcpy_s(&key, sizeof(RbTreeKey), s, sizeof(RbTreeKey)) != EOK) {
533 return CMR_ERROR_INVALID_OPERATION;
534 }
535 s += sizeof(RbTreeKey);
536
537 uint32_t valueSize;
538 if (memcpy_s(&valueSize, sizeof(RbTreeKey), s, sizeof(uint32_t)) != EOK) {
539 return CMR_ERROR_INVALID_OPERATION;
540 }
541 s += sizeof(uint32_t);
542
543 uint32_t sz = headerSize + valueSize;
544 if (remaining < sz) {
545 return CMR_ERROR_BUFFER_TOO_SMALL;
546 }
547
548 RbTreeValue value = NULL;
549 int rc = dec(&value, s, valueSize);
550 if (rc != CM_SUCCESS) {
551 return rc;
552 }
553
554 rc = RbTreeInsert(t, key, value);
555 if (rc != CM_SUCCESS) {
556 freeFunc(&value);
557 return rc;
558 }
559 off += sz;
560 }
561 return CM_SUCCESS;
562 }
563
TraverseDestroy(struct RbTree * t,struct RbTreeNode * x)564 static void TraverseDestroy(struct RbTree *t, struct RbTreeNode *x)
565 {
566 if (x != t->nil) {
567 TraverseDestroy(t, x->left);
568 x->left = t->nil;
569 TraverseDestroy(t, x->right);
570 x->right = t->nil;
571 CMFree(x);
572 }
573 }
574
RbTreeDestroy(struct RbTree * t)575 static void RbTreeDestroy(struct RbTree *t)
576 {
577 if (t == NULL) {
578 return;
579 }
580
581 TraverseDestroy(t, t->root);
582 CMFree(t->nil);
583 t->nil = NULL;
584 t->root = NULL;
585 }
586
RbTreeDestroyEx(struct RbTree * t,RbTreeNodeHandler freeFunc)587 void RbTreeDestroyEx(struct RbTree *t, RbTreeNodeHandler freeFunc)
588 {
589 if ((t == NULL) || (freeFunc == NULL)) {
590 return;
591 }
592
593 TraverseInOrder(t, t->root, freeFunc, NULL);
594 RbTreeDestroy(t);
595 }
596
597 #ifdef __cplusplus
598 }
599 #endif
600 // LCOV_EXCL_STOP