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