14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License.
54514f5e3Sopenharmony_ci * You may obtain a copy of the License at
64514f5e3Sopenharmony_ci *
74514f5e3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84514f5e3Sopenharmony_ci *
94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and
134514f5e3Sopenharmony_ci * limitations under the License.
144514f5e3Sopenharmony_ci */
154514f5e3Sopenharmony_ci
164514f5e3Sopenharmony_ci#include "ecmascript/mem/dyn_chunk.h"
174514f5e3Sopenharmony_ci
184514f5e3Sopenharmony_ci#include "securec.h"
194514f5e3Sopenharmony_ci
204514f5e3Sopenharmony_cinamespace panda::ecmascript {
214514f5e3Sopenharmony_ciint DynChunk::Expand(size_t newSize)
224514f5e3Sopenharmony_ci{
234514f5e3Sopenharmony_ci    if (newSize > allocatedSize_) {
244514f5e3Sopenharmony_ci        if (error_) {
254514f5e3Sopenharmony_ci            return FAILURE;
264514f5e3Sopenharmony_ci        }
274514f5e3Sopenharmony_ci        ASSERT(allocatedSize_ <= std::numeric_limits<size_t>::max() / ALLOCATE_MULTIPLIER);
284514f5e3Sopenharmony_ci        size_t size = allocatedSize_ * ALLOCATE_MULTIPLIER;
294514f5e3Sopenharmony_ci        if (size > newSize) {
304514f5e3Sopenharmony_ci            newSize = size;
314514f5e3Sopenharmony_ci        }
324514f5e3Sopenharmony_ci        newSize = std::max(newSize, ALLOCATE_MIN_SIZE);
334514f5e3Sopenharmony_ci        auto *newBuf = chunk_->NewArray<uint8_t>(newSize);
344514f5e3Sopenharmony_ci        if (newBuf == nullptr) {
354514f5e3Sopenharmony_ci            error_ = true;
364514f5e3Sopenharmony_ci            return FAILURE;
374514f5e3Sopenharmony_ci        }
384514f5e3Sopenharmony_ci        if (memset_s(newBuf, newSize, 0, newSize) != EOK) {
394514f5e3Sopenharmony_ci            error_ = true;
404514f5e3Sopenharmony_ci            return FAILURE;
414514f5e3Sopenharmony_ci        }
424514f5e3Sopenharmony_ci        if (buf_ != nullptr) {
434514f5e3Sopenharmony_ci            if (memcpy_s(newBuf, size_, buf_, size_) != EOK) {
444514f5e3Sopenharmony_ci                error_ = true;
454514f5e3Sopenharmony_ci                return FAILURE;
464514f5e3Sopenharmony_ci            }
474514f5e3Sopenharmony_ci        }
484514f5e3Sopenharmony_ci        buf_ = newBuf;
494514f5e3Sopenharmony_ci        allocatedSize_ = newSize;
504514f5e3Sopenharmony_ci    }
514514f5e3Sopenharmony_ci    return SUCCESS;
524514f5e3Sopenharmony_ci}
534514f5e3Sopenharmony_ci
544514f5e3Sopenharmony_ciint DynChunk::Insert(uint32_t position, size_t len)
554514f5e3Sopenharmony_ci{
564514f5e3Sopenharmony_ci    if (size_ < position) {
574514f5e3Sopenharmony_ci        return FAILURE;
584514f5e3Sopenharmony_ci    }
594514f5e3Sopenharmony_ci    if (Expand(size_ + len) != 0) {
604514f5e3Sopenharmony_ci        return FAILURE;
614514f5e3Sopenharmony_ci    }
624514f5e3Sopenharmony_ci    size_t moveSize = size_ - position;
634514f5e3Sopenharmony_ci    // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
644514f5e3Sopenharmony_ci    if (memmove_s(buf_ + position + len, moveSize, buf_ + position, moveSize) != EOK) {
654514f5e3Sopenharmony_ci        return FAILURE;
664514f5e3Sopenharmony_ci    }
674514f5e3Sopenharmony_ci    size_ += len;
684514f5e3Sopenharmony_ci    return SUCCESS;
694514f5e3Sopenharmony_ci}
704514f5e3Sopenharmony_ci
714514f5e3Sopenharmony_ciint DynChunk::Emit(const uint8_t *data, size_t length)
724514f5e3Sopenharmony_ci{
734514f5e3Sopenharmony_ci    if (UNLIKELY((size_ + length) > allocatedSize_)) {
744514f5e3Sopenharmony_ci        if (Expand(size_ + length) != 0) {
754514f5e3Sopenharmony_ci            return FAILURE;
764514f5e3Sopenharmony_ci        }
774514f5e3Sopenharmony_ci    }
784514f5e3Sopenharmony_ci
794514f5e3Sopenharmony_ci    if (memcpy_s(buf_ + size_,  // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
804514f5e3Sopenharmony_ci                 length, data, length) != EOK) {
814514f5e3Sopenharmony_ci        return FAILURE;
824514f5e3Sopenharmony_ci    }
834514f5e3Sopenharmony_ci    size_ += length;
844514f5e3Sopenharmony_ci    return SUCCESS;
854514f5e3Sopenharmony_ci}
864514f5e3Sopenharmony_ci
874514f5e3Sopenharmony_ciint DynChunk::EmitChar(uint8_t c)
884514f5e3Sopenharmony_ci{
894514f5e3Sopenharmony_ci    return Emit(&c, 1);
904514f5e3Sopenharmony_ci}
914514f5e3Sopenharmony_ci
924514f5e3Sopenharmony_ciint DynChunk::EmitSelf(size_t offset, size_t length)
934514f5e3Sopenharmony_ci{
944514f5e3Sopenharmony_ci    if (UNLIKELY((size_ + length) > allocatedSize_)) {
954514f5e3Sopenharmony_ci        if (Expand(size_ + length) != 0) {
964514f5e3Sopenharmony_ci            return FAILURE;
974514f5e3Sopenharmony_ci        }
984514f5e3Sopenharmony_ci    }
994514f5e3Sopenharmony_ci
1004514f5e3Sopenharmony_ci    if (memcpy_s(buf_ + size_,  // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
1014514f5e3Sopenharmony_ci                 length,
1024514f5e3Sopenharmony_ci                 buf_ + offset,  // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
1034514f5e3Sopenharmony_ci                 length) != EOK) {
1044514f5e3Sopenharmony_ci        return FAILURE;
1054514f5e3Sopenharmony_ci    }
1064514f5e3Sopenharmony_ci    size_ += length;
1074514f5e3Sopenharmony_ci    return SUCCESS;
1084514f5e3Sopenharmony_ci}
1094514f5e3Sopenharmony_ci
1104514f5e3Sopenharmony_ciint DynChunk::EmitStr(const char *str)
1114514f5e3Sopenharmony_ci{
1124514f5e3Sopenharmony_ci    return Emit(reinterpret_cast<const uint8_t *>(str), strlen(str) + 1);
1134514f5e3Sopenharmony_ci}
1144514f5e3Sopenharmony_ci}  // namespace panda::ecmascript
115