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
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 if (v != NULL) {
243 v->p = u->p;
244 }
245 }
246
Minimum(const struct RbTree * t,struct RbTreeNode * x)247 static struct RbTreeNode *Minimum(const struct RbTree *t, struct RbTreeNode *x)
248 {
249 while (x->left != t->nil) {
250 x = x->left;
251 }
252 return x;
253 }
254
DeleteFixUpBlack(struct RbTree * t,struct RbTreeNode ** treeNode)255 static void DeleteFixUpBlack(struct RbTree *t, struct RbTreeNode **treeNode)
256 {
257 struct RbTreeNode *w = NULL;
258 struct RbTreeNode *x = *treeNode;
259 w = x->p->right;
260 if (IS_RED(w)) {
261 SET_BLACK(w);
262 SET_RED(x->p);
263 LeftRotate(t, x->p);
264 w = x->p->right;
265 }
266 if (IS_BLACK(w->left) && IS_BLACK(w->right)) {
267 SET_RED(w);
268 x = x->p;
269 } else {
270 if (IS_BLACK(w->right)) {
271 SET_BLACK(w->left);
272 SET_RED(w);
273 RightRotate(t, w);
274 w = x->p->right;
275 }
276
277 SET_COLOR(w, COLOR(x->p));
278 SET_BLACK(x->p);
279 SET_BLACK(w->right);
280 LeftRotate(t, x->p);
281 x = t->root;
282 }
283 *treeNode = x;
284 }
285
DeleteFixUpRed(struct RbTree * t,struct RbTreeNode ** treeNode)286 static void DeleteFixUpRed(struct RbTree *t, struct RbTreeNode **treeNode)
287 {
288 struct RbTreeNode *w = NULL;
289 struct RbTreeNode *x = *treeNode;
290
291 w = x->p->left;
292 if (IS_RED(w)) {
293 SET_BLACK(w);
294 SET_RED(x->p);
295 RightRotate(t, x->p);
296 w = x->p->left;
297 }
298 if (IS_BLACK(w->right) && IS_BLACK(w->left)) {
299 SET_RED(w);
300 x = x->p;
301 } else {
302 if (IS_BLACK(w->left)) {
303 SET_BLACK(w->right);
304 SET_RED(w);
305 LeftRotate(t, w);
306 w = x->p->left;
307 }
308
309 SET_COLOR(w, COLOR(x->p));
310 SET_BLACK(x->p);
311 SET_BLACK(w->left);
312 RightRotate(t, x->p);
313 x = t->root;
314 }
315 *treeNode = x;
316 }
317
DeleteFixUp(struct RbTree * t,struct RbTreeNode * x)318 static void DeleteFixUp(struct RbTree *t, struct RbTreeNode *x)
319 {
320 while (x != t->root && IS_BLACK(x)) {
321 if (x == x->p->left) {
322 DeleteFixUpBlack(t, &x);
323 } else {
324 DeleteFixUpRed(t, &x);
325 }
326 }
327 SET_BLACK(x);
328 }
329
RbTreeDelete(struct RbTree * t,struct RbTreeNode * z)330 int32_t RbTreeDelete(struct RbTree *t, struct RbTreeNode *z)
331 {
332 if (t == NULL) {
333 CM_LOG_E("input param is invaild");
334 return CM_FAILURE;
335 }
336 struct RbTreeNode *x = NULL;
337 struct RbTreeNode *y = z;
338 RbTreeKey yColor = COLOR(y);
339
340 if (z->left == t->nil) {
341 x = z->right;
342 Transplant(t, z, z->right);
343 } else if (z->right == t->nil) {
344 x = z->left;
345 Transplant(t, z, z->left);
346 } else {
347 y = Minimum(t, z->right);
348 yColor = COLOR(y);
349 x = y->right;
350 if (y->p == z) {
351 x->p = y;
352 } else {
353 Transplant(t, y, y->right);
354 y->right = z->right;
355 if (y->right != NULL) {
356 y->right->p = y;
357 }
358 }
359 Transplant(t, z, y);
360 y->left = z->left;
361 if (y->left != NULL) {
362 y->left->p = y;
363 }
364 SET_COLOR(y, COLOR(z));
365 }
366 if (yColor == BLACK) {
367 DeleteFixUp(t, x);
368 }
369 CMFree(z);
370 return CM_SUCCESS;
371 }
372
RbTreeFindNode(struct RbTreeNode ** nodePtr,RbTreeKey key,const struct RbTree * tree)373 int32_t RbTreeFindNode(struct RbTreeNode **nodePtr, RbTreeKey key, const struct RbTree *tree)
374 {
375 if (tree == NULL || nodePtr == NULL) {
376 CM_LOG_E("input param is invaild");
377 return CM_FAILURE;
378 }
379
380 *nodePtr = NULL;
381
382 struct RbTreeNode *n = tree->root;
383 while (n != tree->nil) {
384 if (KEY(n) == key) {
385 *nodePtr = n;
386 return CM_SUCCESS;
387 } else if (key < KEY(n)) {
388 n = n->left;
389 } else {
390 n = n->right;
391 }
392 }
393 return CMR_ERROR_NOT_FOUND;
394 }
395
TraverseInOrder(const struct RbTree * t,const struct RbTreeNode * x,RbTreeNodeHandler handler,const void * context)396 static void TraverseInOrder(const struct RbTree *t, const struct RbTreeNode *x,
397 RbTreeNodeHandler handler, const void *context)
398 {
399 if (x == t->nil) {
400 return;
401 }
402 TraverseInOrder(t, x->left, handler, context);
403 handler(KEY(x), x->value, context);
404 TraverseInOrder(t, x->right, handler, context);
405 }
406
TraversePreOrder(const struct RbTree * t,const struct RbTreeNode * x,RbTreeNodeHandler handler,const void * context)407 static void TraversePreOrder(const struct RbTree *t, const struct RbTreeNode *x,
408 RbTreeNodeHandler handler, const void *context)
409 {
410 if (x == t->nil) {
411 return;
412 }
413 handler(KEY(x), x->value, context);
414 TraversePreOrder(t, x->left, handler, context);
415 TraversePreOrder(t, x->right, handler, context);
416 }
417
TraversePostOrder(const struct RbTree * t,const struct RbTreeNode * x,RbTreeNodeHandler handler,const void * context)418 static void TraversePostOrder(const struct RbTree *t, const struct RbTreeNode *x,
419 RbTreeNodeHandler handler, const void *context)
420 {
421 if (x == t->nil) {
422 return;
423 }
424 TraversePostOrder(t, x->left, handler, context);
425 TraversePostOrder(t, x->right, handler, context);
426 handler(KEY(x), x->value, context);
427 }
428
Encoder(RbTreeKey key,RbTreeValue value,const void * context)429 static void Encoder(RbTreeKey key, RbTreeValue value, const void *context)
430 {
431 struct EncoderContext *ctx = (struct EncoderContext *)context;
432 if (ctx->status != CM_SUCCESS) {
433 CM_LOG_E("already failed: %d", ctx->status); /* already failed. do not continue */
434 return;
435 }
436
437 uint32_t valueSize = 0;
438 int rc = ctx->enc(value, NULL, &valueSize); /* get value size */
439 if (rc != CM_SUCCESS) {
440 CM_LOG_E("value encoder get length failed: %d", rc);
441 ctx->status = rc;
442 return;
443 }
444
445 uint32_t keySize = sizeof(RbTreeKey);
446 if (valueSize > (UINT32_MAX - keySize - sizeof(uint32_t))) {
447 ctx->status = CMR_ERROR_INVALID_ARGUMENT;
448 return;
449 }
450
451 /* each code is encoded ad (key | encoded_value_len | encoded_value)
452 encoded_value_len is uint32_t. */
453 uint32_t sz = keySize + sizeof(uint32_t) + valueSize;
454 if (sz > (UINT32_MAX - ctx->off)) {
455 ctx->status = CMR_ERROR_INVALID_ARGUMENT;
456 return;
457 }
458
459 /* if buffer is provided, do the actual encoding */
460 if (ctx->buf != NULL) {
461 if (ctx->off + sz > ctx->len) {
462 ctx->status = CMR_ERROR_BUFFER_TOO_SMALL;
463 return;
464 }
465 uint8_t *buf = ctx->buf + ctx->off;
466 if (memcpy_s(buf, ctx->len - ctx->off, &key, keySize) != EOK) {
467 ctx->status = CMR_ERROR_INVALID_ARGUMENT;
468 return;
469 }
470 buf += keySize;
471 if (memcpy_s(buf, ctx->len - ctx->off - keySize, &valueSize, sizeof(uint32_t)) != EOK) {
472 ctx->status = CMR_ERROR_INVALID_ARGUMENT;
473 return;
474 }
475 buf += sizeof(uint32_t);
476 rc = ctx->enc(value, buf, &valueSize);
477 if (rc != CM_SUCCESS) {
478 CM_LOG_E("value encoder encoding failed: %d", rc);
479 ctx->status = rc;
480 return;
481 }
482 }
483 /* in any case, updata offset in context. */
484 ctx->off += sz;
485 }
486
RbTreeEncode(const struct RbTree * t,RbTreeValueEncoder enc,uint8_t * buf,uint32_t * size)487 int32_t RbTreeEncode(const struct RbTree *t, RbTreeValueEncoder enc, uint8_t *buf, uint32_t *size)
488 {
489 if (t == NULL || t->root == NULL || enc == NULL || size == NULL) {
490 CM_LOG_E("input param is invaild");
491 return CM_FAILURE;
492 }
493
494 struct EncoderContext ctx = {
495 .buf = buf,
496 .off = 0,
497 .len = *size,
498 .status = CM_SUCCESS,
499 .enc = enc,
500 };
501
502 TraverseInOrder(t, t->root, Encoder, &ctx);
503 if (ctx.status != CM_SUCCESS) {
504 return ctx.status;
505 }
506 *size = ctx.off;
507 return CM_SUCCESS;
508 }
509
RbTreeDecode(struct RbTree * t,RbTreeValueDecoder dec,RbTreeValueFree freeFunc,uint8_t * buf,uint32_t size)510 int32_t RbTreeDecode(struct RbTree *t, RbTreeValueDecoder dec, RbTreeValueFree freeFunc,
511 uint8_t *buf, uint32_t size)
512 {
513 if (t == NULL || t->root == NULL || dec == NULL || freeFunc == NULL || buf == NULL || size == 0) {
514 CM_LOG_E("input param is invaild");
515 return CM_FAILURE;
516 }
517
518 uint32_t off = 0;
519 while (off < size) {
520 uint32_t remaining = size - off;
521 uint32_t headerSize = sizeof(RbTreeKey) + sizeof(uint32_t);
522
523 if (remaining < headerSize) {
524 /* something is wrong */
525 return CMR_ERROR_BUFFER_TOO_SMALL;
526 }
527
528 uint8_t *s = buf + off;
529
530 RbTreeKey key;
531 if (memcpy_s(&key, sizeof(RbTreeKey), s, sizeof(RbTreeKey)) != EOK) {
532 return CMR_ERROR_INVALID_OPERATION;
533 }
534 s += sizeof(RbTreeKey);
535
536 uint32_t valueSize;
537 if (memcpy_s(&valueSize, sizeof(RbTreeKey), s, sizeof(uint32_t)) != EOK) {
538 return CMR_ERROR_INVALID_OPERATION;
539 }
540 s += sizeof(uint32_t);
541
542 uint32_t sz = headerSize + valueSize;
543 if (remaining < sz) {
544 return CMR_ERROR_BUFFER_TOO_SMALL;
545 }
546
547 RbTreeValue value = NULL;
548 int rc = dec(&value, s, valueSize);
549 if (rc != CM_SUCCESS) {
550 return rc;
551 }
552
553 rc = RbTreeInsert(t, key, value);
554 if (rc != CM_SUCCESS) {
555 freeFunc(&value);
556 return rc;
557 }
558 off += sz;
559 }
560 return CM_SUCCESS;
561 }
562
TraverseDestroy(struct RbTree * t,struct RbTreeNode * x)563 static void TraverseDestroy(struct RbTree *t, struct RbTreeNode *x)
564 {
565 if (x != t->nil) {
566 TraverseDestroy(t, x->left);
567 x->left = t->nil;
568 TraverseDestroy(t, x->right);
569 x->right = t->nil;
570 CMFree(x);
571 }
572 }
573
RbTreeDestroy(struct RbTree * t)574 static void RbTreeDestroy(struct RbTree *t)
575 {
576 if (t == NULL) {
577 return;
578 }
579
580 TraverseDestroy(t, t->root);
581 CMFree(t->nil);
582 t->nil = NULL;
583 t->root = NULL;
584 }
585
RbTreeDestroyEx(struct RbTree * t,RbTreeNodeHandler freeFunc)586 void RbTreeDestroyEx(struct RbTree *t, RbTreeNodeHandler freeFunc)
587 {
588 if ((t == NULL) || (freeFunc == NULL)) {
589 return;
590 }
591
592 TraverseInOrder(t, t->root, freeFunc, NULL);
593 RbTreeDestroy(t);
594 }
595
596 #ifdef __cplusplus
597 }
598
599 #endif