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