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 <stdbool.h> /* bool */
17 #include <stddef.h> /* NULL */
18 #include <stdlib.h> /* malloc */
19
20 #include "hilog/log_c.h"
21 #include "../../common/include/pm_ptr_util.h"
22 #include "purgeable_mem_builder_c.h"
23
24 #undef LOG_TAG
25 #define LOG_TAG "PurgeableMemC: Builder"
26
27 /* purgeable mem builder */
28 struct PurgMemBuilder {
29 struct PurgMemBuilder *nextBuilder;
30 PurgMemBuilderFunc Build;
31 void *param;
32 const char *name;
33 };
34
35 /* append a guest builder @newcomer to @head */
36 static void AppendBuilder_(struct PurgMemBuilder *head, struct PurgMemBuilder *newcomer);
37
PurgMemBuilderCreate(PurgMemBuilderFunc func,void * param,const char * name)38 struct PurgMemBuilder *PurgMemBuilderCreate(PurgMemBuilderFunc func, void *param, const char *name)
39 {
40 IF_NULL_LOG_ACTION(func, "func is NULL", return NULL);
41
42 struct PurgMemBuilder *builder = NULL;
43 builder = (struct PurgMemBuilder *)malloc(sizeof(struct PurgMemBuilder));
44 if (!builder) {
45 HILOG_ERROR(LOG_CORE, "%{public}s: malloc struct PurgMemBuilder failed", __func__);
46 return NULL;
47 }
48 builder->Build = func;
49 builder->nextBuilder = NULL;
50 builder->param = param;
51 builder->name = name;
52 return builder;
53 }
54
PurgMemBuilderDestroy(struct PurgMemBuilder * builder)55 bool PurgMemBuilderDestroy(struct PurgMemBuilder *builder)
56 {
57 IF_NULL_LOG_ACTION(builder, "builder is NULL", return true);
58
59 struct PurgMemBuilder *curr = builder;
60 struct PurgMemBuilder *next = NULL;
61 while (curr) {
62 next = curr->nextBuilder;
63 free(curr);
64 curr = next;
65 }
66 /* set input para NULL to avoid UAF */
67 builder = NULL;
68 return true;
69 }
70
PurgMemBuilderAppendFunc(struct PurgMemBuilder * builder,PurgMemBuilderFunc func,void * param,const char * name)71 bool PurgMemBuilderAppendFunc(struct PurgMemBuilder *builder, PurgMemBuilderFunc func, void *param,
72 const char *name)
73 {
74 IF_NULL_LOG_ACTION(builder, "input builder is NULL", return false);
75 IF_NULL_LOG_ACTION(func, "input func is NULL", return false);
76
77 struct PurgMemBuilder *newcomer = PurgMemBuilderCreate(func, param, name);
78 IF_NULL_LOG_ACTION(newcomer, "create new builder failed", return false);
79
80 AppendBuilder_(builder, newcomer);
81 return true;
82 }
83
84 /* build @data content from @builder */
PurgMemBuilderBuildAll(struct PurgMemBuilder * builder,void * data,size_t size)85 bool PurgMemBuilderBuildAll(struct PurgMemBuilder *builder, void *data, size_t size)
86 {
87 if (!(builder->Build)) {
88 HILOG_ERROR(LOG_CORE, "builder has no Build(), %{public}s", builder->name);
89 return true;
90 }
91 if (!(builder->Build(data, size, builder->param))) {
92 HILOG_ERROR(LOG_CORE, "build data failed, name %{public}s", builder->name ?: "NULL");
93 return false;
94 }
95 if (!(builder->nextBuilder)) {
96 return true;
97 }
98 return PurgMemBuilderBuildAll(builder->nextBuilder, data, size);
99 }
100
PurgMemBuilderAppendBuilder(struct PurgMemBuilder * builder,struct PurgMemBuilder * newcomer)101 bool PurgMemBuilderAppendBuilder(struct PurgMemBuilder *builder, struct PurgMemBuilder *newcomer)
102 {
103 IF_NULL_LOG_ACTION(builder, "input builder is NULL", return false);
104 IF_NULL_LOG_ACTION(newcomer, "input newcomer is NULL", return false);
105
106 AppendBuilder_(builder, newcomer);
107 return true;
108 }
109
110 /* append a guest builder @newcomer to @head */
AppendBuilder_(struct PurgMemBuilder * head,struct PurgMemBuilder * newcomer)111 static void AppendBuilder_(struct PurgMemBuilder *head, struct PurgMemBuilder *newcomer)
112 {
113 if (!head->nextBuilder) {
114 head->nextBuilder = newcomer;
115 return;
116 }
117 return AppendBuilder_(head->nextBuilder, newcomer);
118 }
119