• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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