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 == NULL) {
89         PM_HILOG_ERROR_C(LOG_CORE, "%{public}s: builder is NULL!", __func__);
90         return false;
91     }
92     if (!(builder->Build)) {
93         PM_HILOG_ERROR_C(LOG_CORE, "builder has no Build(), %{public}s", builder->name);
94         return true;
95     }
96     if (!(builder->Build(data, size, builder->param))) {
97         PM_HILOG_ERROR_C(LOG_CORE, "build data failed, name %{public}s", builder->name ?: "NULL");
98         return false;
99     }
100     if (!(builder->nextBuilder)) {
101         return true;
102     }
103     return PurgMemBuilderBuildAll(builder->nextBuilder, data, size);
104 }
105 
PurgMemBuilderAppendBuilder(struct PurgMemBuilder * builder,struct PurgMemBuilder * newcomer)106 bool PurgMemBuilderAppendBuilder(struct PurgMemBuilder *builder, struct PurgMemBuilder *newcomer)
107 {
108     IF_NULL_LOG_ACTION(builder, "input builder is NULL", return false);
109     IF_NULL_LOG_ACTION(newcomer, "input newcomer is NULL", return false);
110 
111     AppendBuilder(builder, newcomer);
112     return true;
113 }
114 
115 /* append a guest builder @newcomer to @head */
AppendBuilder(struct PurgMemBuilder * head,struct PurgMemBuilder * newcomer)116 static void AppendBuilder(struct PurgMemBuilder *head, struct PurgMemBuilder *newcomer)
117 {
118     if (head == NULL) {
119         PM_HILOG_ERROR_C(LOG_CORE, "%{public}s: head is NULL!", __func__);
120         return;
121     }
122     if (!head->nextBuilder) {
123         head->nextBuilder = newcomer;
124         return;
125     }
126     return AppendBuilder(head->nextBuilder, newcomer);
127 }
128