• 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)->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