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