Skip to content

Commit

Permalink
refactor(ios): avoid mutex crash in special app environment (#4020)
Browse files Browse the repository at this point in the history
* fix(ios): check static invalid mutex crash

* fix(ios): move static maps to heap for checking static overflow crash
  • Loading branch information
etkmao authored Sep 10, 2024
1 parent 0907206 commit 592c010
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 94 deletions.
1 change: 1 addition & 0 deletions dom/include/dom/layout_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ class LayoutNode {
const std::vector<std::string>& style_delete) = 0;
};

void InitLayoutConsts();
std::shared_ptr<LayoutNode> CreateLayoutNode();

} // namespace dom
Expand Down
1 change: 1 addition & 0 deletions dom/src/dom/root_node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ bool DomNodeStyleDiffer::Calculate(const std::shared_ptr<hippy::dom::RootNode>&
}

RootNode::RootNode(uint32_t id) : DomNode(id, 0, 0, "", "", nullptr, nullptr, {}) {
InitLayoutConsts();
SetRenderInfo({id, 0, 0});
animation_manager_ = std::make_shared<AnimationManager>();
interceptors_.push_back(animation_manager_);
Expand Down
145 changes: 79 additions & 66 deletions dom/src/dom/taitank_layout_node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,75 +30,82 @@
namespace hippy {
inline namespace dom {

const std::map<std::string, OverflowType> kOverflowMap = {{"visible", OverflowType::OVERFLOW_VISIBLE},
{"hidden", OverflowType::OVERFLOW_HIDDEN},
{"scroll", OverflowType::OVERFLOW_SCROLL}};

const std::map<std::string, FlexDirection> kFlexDirectionMap = {
{"row", FlexDirection::FLEX_DIRECTION_ROW},
{"row-reverse", FlexDirection::FLEX_DIRECTION_ROW_REVERSE},
{"column", FlexDirection::FLEX_DIRECTION_COLUMN},
{"column-reverse", FlexDirection::FLEX_DIRECTION_COLUNM_REVERSE}};

const std::map<std::string, FlexWrapMode> kWrapModeMap = {{"nowrap", FlexWrapMode::FLEX_NO_WRAP},
{"wrap", FlexWrapMode::FLEX_WRAP},
{"wrap-reverse", FlexWrapMode::FLEX_WRAP_REVERSE}};

const std::map<std::string, FlexAlign> kJustifyMap = {{"flex-start", FlexAlign::FLEX_ALIGN_START},
{"center", FlexAlign::FLEX_ALIGN_CENTER},
{"flex-end", FlexAlign::FLEX_ALIGN_END},
{"space-between", FlexAlign::FLEX_ALIGN_SPACE_BETWEEN},
{"space-around", FlexAlign::FLEX_ALIGN_SPACE_AROUND},
{"space-evenly", FlexAlign::FLEX_ALIGN_SPACE_EVENLY}};

const std::map<std::string, FlexAlign> kAlignMap = {{"auto", FlexAlign::FLEX_ALIGN_AUTO},
{"flex-start", FlexAlign::FLEX_ALIGN_START},
{"center", FlexAlign::FLEX_ALIGN_CENTER},
{"flex-end", FlexAlign::FLEX_ALIGN_END},
{"stretch", FlexAlign::FLEX_ALIGN_STRETCH},
{"baseline", FlexAlign::FLEX_ALIGN_BASE_LINE},
{"space-between", FlexAlign::FLEX_ALIGN_SPACE_BETWEEN},
{"space-around", FlexAlign::FLEX_ALIGN_SPACE_AROUND}};

const std::map<std::string, CSSDirection> kMarginMap = {{kMargin, CSSDirection::CSS_ALL},
{kMarginVertical, CSSDirection::CSS_VERTICAL},
{kMarginHorizontal, CSSDirection::CSS_HORIZONTAL},
{kMarginLeft, CSSDirection::CSS_LEFT},
{kMarginRight, CSSDirection::CSS_RIGHT},
{kMarginTop, CSSDirection::CSS_TOP},
{kMarginBottom, CSSDirection::CSS_BOTTOM}};

const std::map<std::string, CSSDirection> kPaddingMap = {{kPadding, CSSDirection::CSS_ALL},
{kPaddingVertical, CSSDirection::CSS_VERTICAL},
{kPaddingHorizontal, CSSDirection::CSS_HORIZONTAL},
{kPaddingLeft, CSSDirection::CSS_LEFT},
{kPaddingRight, CSSDirection::CSS_RIGHT},
{kPaddingTop, CSSDirection::CSS_TOP},
{kPaddingBottom, CSSDirection::CSS_BOTTOM}};

const std::map<std::string, CSSDirection> kPositionMap = {{kLeft, CSSDirection::CSS_LEFT},
{kRight, CSSDirection::CSS_RIGHT},
{kTop, CSSDirection::CSS_TOP},
{kBottom, CSSDirection::CSS_BOTTOM}};

const std::map<std::string, CSSDirection> kBorderMap = {{kBorderWidth, CSSDirection::CSS_ALL},
{kBorderLeftWidth, CSSDirection::CSS_LEFT},
{kBorderTopWidth, CSSDirection::CSS_TOP},
{kBorderRightWidth, CSSDirection::CSS_RIGHT},
{kBorderBottomWidth, CSSDirection::CSS_BOTTOM}};

const std::map<std::string, PositionType> kPositionTypeMap = {{"relative", PositionType::POSITION_TYPE_RELATIVE},
{"absolute", PositionType::POSITION_TYPE_ABSOLUTE}};

const std::map<std::string, DisplayType> kDisplayTypeMap = {{"none", DisplayType::DISPLAY_TYPE_NONE}};

const std::map<std::string, TaitankDirection> kDirectionMap = {
{"inherit", DIRECTION_INHERIT}, {"ltr", DIRECTION_LTR}, {"rtl", DIRECTION_RTL}};
class TaitankLayoutConsts {
public:
const std::map<std::string, OverflowType> kOverflowMap = {{"visible", OverflowType::OVERFLOW_VISIBLE},
{"hidden", OverflowType::OVERFLOW_HIDDEN},
{"scroll", OverflowType::OVERFLOW_SCROLL}};

const std::map<std::string, FlexDirection> kFlexDirectionMap = {
{"row", FlexDirection::FLEX_DIRECTION_ROW},
{"row-reverse", FlexDirection::FLEX_DIRECTION_ROW_REVERSE},
{"column", FlexDirection::FLEX_DIRECTION_COLUMN},
{"column-reverse", FlexDirection::FLEX_DIRECTION_COLUNM_REVERSE}};

const std::map<std::string, FlexWrapMode> kWrapModeMap = {{"nowrap", FlexWrapMode::FLEX_NO_WRAP},
{"wrap", FlexWrapMode::FLEX_WRAP},
{"wrap-reverse", FlexWrapMode::FLEX_WRAP_REVERSE}};

const std::map<std::string, FlexAlign> kJustifyMap = {{"flex-start", FlexAlign::FLEX_ALIGN_START},
{"center", FlexAlign::FLEX_ALIGN_CENTER},
{"flex-end", FlexAlign::FLEX_ALIGN_END},
{"space-between", FlexAlign::FLEX_ALIGN_SPACE_BETWEEN},
{"space-around", FlexAlign::FLEX_ALIGN_SPACE_AROUND},
{"space-evenly", FlexAlign::FLEX_ALIGN_SPACE_EVENLY}};

const std::map<std::string, FlexAlign> kAlignMap = {{"auto", FlexAlign::FLEX_ALIGN_AUTO},
{"flex-start", FlexAlign::FLEX_ALIGN_START},
{"center", FlexAlign::FLEX_ALIGN_CENTER},
{"flex-end", FlexAlign::FLEX_ALIGN_END},
{"stretch", FlexAlign::FLEX_ALIGN_STRETCH},
{"baseline", FlexAlign::FLEX_ALIGN_BASE_LINE},
{"space-between", FlexAlign::FLEX_ALIGN_SPACE_BETWEEN},
{"space-around", FlexAlign::FLEX_ALIGN_SPACE_AROUND}};

const std::map<std::string, CSSDirection> kMarginMap = {{kMargin, CSSDirection::CSS_ALL},
{kMarginVertical, CSSDirection::CSS_VERTICAL},
{kMarginHorizontal, CSSDirection::CSS_HORIZONTAL},
{kMarginLeft, CSSDirection::CSS_LEFT},
{kMarginRight, CSSDirection::CSS_RIGHT},
{kMarginTop, CSSDirection::CSS_TOP},
{kMarginBottom, CSSDirection::CSS_BOTTOM}};

const std::map<std::string, CSSDirection> kPaddingMap = {{kPadding, CSSDirection::CSS_ALL},
{kPaddingVertical, CSSDirection::CSS_VERTICAL},
{kPaddingHorizontal, CSSDirection::CSS_HORIZONTAL},
{kPaddingLeft, CSSDirection::CSS_LEFT},
{kPaddingRight, CSSDirection::CSS_RIGHT},
{kPaddingTop, CSSDirection::CSS_TOP},
{kPaddingBottom, CSSDirection::CSS_BOTTOM}};

const std::map<std::string, CSSDirection> kPositionMap = {{kLeft, CSSDirection::CSS_LEFT},
{kRight, CSSDirection::CSS_RIGHT},
{kTop, CSSDirection::CSS_TOP},
{kBottom, CSSDirection::CSS_BOTTOM}};

const std::map<std::string, CSSDirection> kBorderMap = {{kBorderWidth, CSSDirection::CSS_ALL},
{kBorderLeftWidth, CSSDirection::CSS_LEFT},
{kBorderTopWidth, CSSDirection::CSS_TOP},
{kBorderRightWidth, CSSDirection::CSS_RIGHT},
{kBorderBottomWidth, CSSDirection::CSS_BOTTOM}};

const std::map<std::string, PositionType> kPositionTypeMap = {{"relative", PositionType::POSITION_TYPE_RELATIVE},
{"absolute", PositionType::POSITION_TYPE_ABSOLUTE}};

const std::map<std::string, DisplayType> kDisplayTypeMap = {{"none", DisplayType::DISPLAY_TYPE_NONE}};

const std::map<std::string, TaitankDirection> kDirectionMap = {
{"inherit", DIRECTION_INHERIT}, {"ltr", DIRECTION_LTR}, {"rtl", DIRECTION_RTL}};
};

static std::shared_ptr<TaitankLayoutConsts> global_layout_consts = nullptr;

#define TAITANK_GET_STYLE_DECL(NAME, TYPE, DEFAULT) \
static TYPE GetStyle##NAME(const std::string& key) { \
auto iter = k##NAME##Map.find(key); \
if (iter != k##NAME##Map.end()) return iter->second; \
if (global_layout_consts == nullptr) return DEFAULT; \
auto &map = global_layout_consts->k##NAME##Map; \
auto iter = map.find(key); \
if (iter != map.end()) return iter->second; \
return DEFAULT; \
}

Expand Down Expand Up @@ -814,6 +821,12 @@ void TaitankLayoutNode::Deallocate() {
engine_node_ = nullptr;
}

void InitLayoutConsts() {
if (global_layout_consts == nullptr) {
global_layout_consts = std::make_shared<TaitankLayoutConsts>();
}
}

std::shared_ptr<LayoutNode> CreateLayoutNode() { return std::make_shared<TaitankLayoutNode>(); }

} // namespace dom
Expand Down
1 change: 1 addition & 0 deletions dom/src/dom/yoga_layout_node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,7 @@ void YogaLayoutNode::Deallocate() {
YGConfigFree(yoga_config_);
}

void InitLayoutConsts() {}
std::shared_ptr<LayoutNode> CreateLayoutNode() { return std::make_shared<YogaLayoutNode>(); }

} // namespace dom
Expand Down
22 changes: 22 additions & 0 deletions driver/js/include/driver/napi/jsc/jsc_ctx.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

#include <mutex>
#include <vector>
#include <set>

#include "footstone/logging.h"
#include "footstone/string_view.h"
Expand Down Expand Up @@ -63,6 +64,27 @@ struct ConstructorData {
}
};

class ConstructorDataManager {
public:
void SaveConstructorDataPtr(void* ptr) {
std::lock_guard<std::mutex> lock(mutex_);
constructor_data_ptr_set_.insert(ptr);
}

void ClearConstructorDataPtr(void* ptr) {
std::lock_guard<std::mutex> lock(mutex_);
constructor_data_ptr_set_.erase(ptr);
}

bool IsValidConstructorDataPtr(void* ptr) {
std::lock_guard<std::mutex> lock(mutex_);
return constructor_data_ptr_set_.find(ptr) != constructor_data_ptr_set_.end();
}
private:
std::set<void*> constructor_data_ptr_set_;
std::mutex mutex_;
};

class JSCCtx : public Ctx {
public:
using string_view = footstone::string_view;
Expand Down
7 changes: 0 additions & 7 deletions driver/js/include/driver/vm/jsc/jsc_vm.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,6 @@ class JSCVM : public VM, public std::enable_shared_from_this<JSCVM> {
}

JSContextGroupRef vm_;

static void SaveConstructorDataPtr(void* ptr);
static void ClearConstructorDataPtr(void* ptr);
static bool IsValidConstructorDataPtr(void* ptr);

static std::set<void*> constructor_data_ptr_set_;
static std::mutex mutex_;

virtual std::shared_ptr<CtxValue> ParseJson(const std::shared_ptr<Ctx>& ctx, const string_view& json) override;
virtual std::shared_ptr<Ctx> CreateContext() override;
Expand Down
12 changes: 9 additions & 3 deletions driver/js/src/napi/jsc/jsc_ctx.cc
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,13 @@ constexpr char16_t kSetStr[] = u"set";

static std::once_flag global_class_flag;
static JSClassRef global_class;
static std::shared_ptr<ConstructorDataManager> global_constructor_data_mgr = nullptr;

JSCCtx::JSCCtx(JSContextGroupRef group, std::weak_ptr<VM> vm): vm_(vm) {
std::call_once(global_class_flag, []() {
JSClassDefinition global = kJSClassDefinitionEmpty;
global_class = JSClassCreate(&global);
global_constructor_data_mgr = std::make_shared<ConstructorDataManager>();
});

context_ = JSGlobalContextCreateInGroup(group, global_class);
Expand All @@ -67,7 +69,9 @@ JSCCtx::~JSCCtx() {
JSGlobalContextRelease(context_);
for (auto& [key, item] : constructor_data_holder_) {
item->prototype = nullptr;
JSCVM::ClearConstructorDataPtr(item.get());
if (global_constructor_data_mgr) {
global_constructor_data_mgr->ClearConstructorDataPtr(item.get());
}
}
}

Expand Down Expand Up @@ -260,7 +264,7 @@ std::shared_ptr<CtxValue> JSCCtx::DefineClass(const string_view& name,
if (!private_data) {
return;
}
if (!JSCVM::IsValidConstructorDataPtr(private_data)) {
if (!global_constructor_data_mgr || !global_constructor_data_mgr->IsValidConstructorDataPtr(private_data)) {
return;
}
auto constructor_data = reinterpret_cast<ConstructorData*>(private_data);
Expand Down Expand Up @@ -965,7 +969,9 @@ void* JSCCtx::GetPrivateData(const std::shared_ptr<CtxValue>& object) {
}

void JSCCtx::SaveConstructorData(std::unique_ptr<ConstructorData> constructor_data) {
JSCVM::SaveConstructorDataPtr(constructor_data.get());
if (global_constructor_data_mgr) {
global_constructor_data_mgr->SaveConstructorDataPtr(constructor_data.get());
}
constructor_data_holder_[constructor_data->class_ref] = std::move(constructor_data);
}

Expand Down
18 changes: 0 additions & 18 deletions driver/js/src/vm/jsc/jsc_vm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,6 @@ namespace hippy {
inline namespace driver {
inline namespace vm {

std::set<void*> JSCVM::constructor_data_ptr_set_;
std::mutex JSCVM::mutex_;

std::shared_ptr<CtxValue> JSCVM::ParseJson(const std::shared_ptr<Ctx>& ctx, const string_view& json) {
if (footstone::StringViewUtils::IsEmpty(json)) {
return nullptr;
Expand Down Expand Up @@ -93,21 +90,6 @@ JSStringRef JSCVM::CreateJSCString(const string_view& str_view) {
return ret;
}

void JSCVM::SaveConstructorDataPtr(void* ptr) {
std::lock_guard<std::mutex> lock(mutex_);
constructor_data_ptr_set_.insert(ptr);
}

void JSCVM::ClearConstructorDataPtr(void* ptr) {
std::lock_guard<std::mutex> lock(mutex_);
constructor_data_ptr_set_.erase(ptr);
}

bool JSCVM::IsValidConstructorDataPtr(void* ptr) {
std::lock_guard<std::mutex> lock(mutex_);
return constructor_data_ptr_set_.find(ptr) != constructor_data_ptr_set_.end();
}

}
}
}

0 comments on commit 592c010

Please sign in to comment.