inline bool checkArray(QuickArray<qstring>& a, const char* chks[], int32_t sz) { int32_t i; if ((int32_t)a.size() < sz) return false; for (i = 0; i < sz; i ++) if (!qstrcmp(a[i].c_str(), chks[i])) return false; return true; }
result_t HeapSnapshot::load(const char* fname) { Isolate* isolate = holder(); result_t hr; v8::Local<v8::Value> v; v8::Local<v8::Object> o; QuickArray<int32_t> nodes; QuickArray<int32_t> edges; QuickArray<qstring> names; QuickArray<qstring> node_fields; QuickArray<qstring> node_types; QuickArray<qstring> edge_fields; QuickArray<qstring> edge_types; int32_t node_count, edge_count; static const char* node_fields_chk[] = {"type", "name", "id", "self_size", "edge_count"}; static const char* node_types_chk[] = {"hidden", "array", "string", "object", "code", "closure", "regexp", "number", "native", "synthetic", "concatenated string", "sliced string" }; static const char* edge_fields_chk[] = {"type", "name_or_index", "to_node"}; static const char* edge_types_chk[] = {"context", "element", "property", "internal", "hidden", "shortcut", "weak" }; qstring data; hr = fs_base::ac_readFile(fname, data); if (hr < 0) return hr; hr = json_base::decode(data.c_str(), v); if (hr < 0) return hr; data.resize(0); if (!v->IsObject()) return CHECK_ERROR(CALL_E_INVALID_DATA); o = v8::Local<v8::Object>::Cast(v); hr = GetArray(o->Get(isolate->NewFromUtf8("nodes")), nodes); if (hr < 0) return CHECK_ERROR(CALL_E_INVALID_DATA); hr = GetArray(o->Get(isolate->NewFromUtf8("edges")), edges); if (hr < 0) return CHECK_ERROR(CALL_E_INVALID_DATA); hr = GetArray(o->Get(isolate->NewFromUtf8("strings")), names); if (hr < 0) return CHECK_ERROR(CALL_E_INVALID_DATA); v = o->Get(isolate->NewFromUtf8("snapshot")); if (v.IsEmpty() || !v->IsObject()) return CHECK_ERROR(CALL_E_INVALID_DATA); o = v8::Local<v8::Object>::Cast(v); hr = GetConfigValue(isolate->m_isolate, o, "node_count", node_count); if (hr < 0) return CHECK_ERROR(CALL_E_INVALID_DATA); hr = GetConfigValue(isolate->m_isolate, o, "edge_count", edge_count); if (hr < 0) return CHECK_ERROR(CALL_E_INVALID_DATA); v = o->Get(isolate->NewFromUtf8("meta")); if (v.IsEmpty() || !v->IsObject()) return CHECK_ERROR(CALL_E_INVALID_DATA); o = v8::Local<v8::Object>::Cast(v); hr = GetArray(o->Get(isolate->NewFromUtf8("node_fields")), node_fields); if (hr < 0 || checkArray(node_fields, node_fields_chk, ARRAYSIZE(node_fields_chk))) return CHECK_ERROR(CALL_E_INVALID_DATA); hr = GetArray(o->Get(isolate->NewFromUtf8("edge_fields")), edge_fields); if (hr < 0 || checkArray(edge_fields, edge_fields_chk, ARRAYSIZE(edge_fields_chk))) return CHECK_ERROR(CALL_E_INVALID_DATA); if (node_fields.size() * node_count != nodes.size()) return CHECK_ERROR(CALL_E_INVALID_DATA); if (edge_fields.size() * edge_count != edges.size()) return CHECK_ERROR(CALL_E_INVALID_DATA); v = o->Get(isolate->NewFromUtf8("node_types")); if (v.IsEmpty() || !v->IsArray()) return CHECK_ERROR(CALL_E_INVALID_DATA); hr = GetArray(v8::Local<v8::Array>::Cast(v)->Get(0), node_types); if (hr < 0 || checkArray(node_types, node_types_chk, ARRAYSIZE(node_types_chk))) return CHECK_ERROR(CALL_E_INVALID_DATA); v = o->Get(isolate->NewFromUtf8("edge_types")); if (v.IsEmpty() || !v->IsArray()) return CHECK_ERROR(CALL_E_INVALID_DATA); hr = GetArray(v8::Local<v8::Array>::Cast(v)->Get(0), edge_types); if (hr < 0 || checkArray(edge_types, edge_types_chk, ARRAYSIZE(edge_types_chk))) return CHECK_ERROR(CALL_E_INVALID_DATA); int32_t node_pos = 0, edge_pos = 0; m_nodes = new List(); while (node_pos < node_count) { int32_t _base = node_pos * (int32_t)node_fields.size(); int32_t _node_type = nodes[_base]; int32_t _node_name_id = nodes[_base + 1]; if (_node_name_id < 0 || _node_name_id >= (int32_t)names.size()) return CHECK_ERROR(CALL_E_INVALID_DATA); qstring _node_name = names[_node_name_id]; int32_t _node_id = nodes[_base + 2]; int32_t _node_size = nodes[_base + 3]; int32_t _node_edge = nodes[_base + 4]; obj_ptr<List> _edges = new List(); if (edge_pos + _node_edge > edge_count) return CHECK_ERROR(CALL_E_INVALID_DATA); while (_node_edge --) { int32_t _base = edge_pos * (int32_t)edge_fields.size(); int32_t _edge_type = edges[_base]; int32_t _edge_name_id = edges[_base + 1]; int32_t _edge_toid = edges[_base + 2]; qstring _edge_name; if (is_num_type(_edge_type)) { char buf[64]; sprintf(buf, "%d", _edge_name_id); _edge_name = buf; } else _edge_name = names[_edge_name_id]; if (_edge_toid % node_fields.size() != 0 || _edge_toid >= (int32_t)edges.size()) return CHECK_ERROR(CALL_E_INVALID_DATA); _edge_toid = nodes[_edge_toid + 2]; obj_ptr<HeapGraphEdge> _edge = new HeapGraphEdge(this, _edge_type, _edge_name, _node_id, _edge_toid); _edges->append(_edge); edge_pos ++; } _edges->freeze(); obj_ptr<HeapGraphNode> _node = new HeapGraphNode(_node_type, _node_name, _node_id, _node_size, _edges); _nodes.insert(std::pair<int32_t, int32_t>(_node_id, node_pos)); m_nodes->append(_node); node_pos ++; } m_nodes->freeze(); return 0; }
static result_t run(int32_t loglevel) { if (!s_root) return 0; if (s_now != s_root) return CHECK_ERROR(CALL_E_INVALID_CALL); s_now = NULL; QuickArray<obj_ptr<_case> > stack; QuickArray<std::string> names; QuickArray<std::string> msgs; int i, j; int32_t oldlevel = 0; int32_t cnt = 0, errcnt = 0; char buf[128]; date_t da1, da2; console_base::get_loglevel(oldlevel); console_base::set_loglevel(loglevel); stack.append(s_root); da1.now(); while (stack.size()) { _case *p = stack[stack.size() - 1]; _case *p1, *p2; if (p->m_pos == 0) { for (i = 0; i < (int) p->m_hooks[HOOK_BEFORE].size(); i++) if (v8::Local<v8::Function>::New(isolate, p->m_hooks[HOOK_BEFORE][i])->Call(v8::Undefined(isolate), 0, NULL).IsEmpty()) { console_base::set_loglevel(oldlevel); clear(); return 0; } } if (p->m_pos < (int) p->m_subs.size()) { std::string str(stack.size() * 2, ' '); p1 = p->m_subs[p->m_pos++]; if (p1->m_block.IsEmpty()) { console_base::set_loglevel(oldlevel); if (stack.size() == 1) asyncLog(console_base::_INFO, ""); str.append(logger::highLight()); str.append(p1->m_name); str.append(COLOR_RESET); asyncLog(console_base::_INFO, str); console_base::set_loglevel(loglevel); stack.append(p1); continue; } for (j = 0; j < (int) stack.size(); j++) { p2 = stack[j]; for (i = 0; i < (int) p2->m_hooks[HOOK_BEFORECASE].size(); i++) if (v8::Local<v8::Function>::New(isolate, p2->m_hooks[HOOK_BEFORECASE][i])->Call(v8::Undefined(isolate), 0, NULL).IsEmpty()) { console_base::set_loglevel(oldlevel); clear(); return 0; } } cnt++; { v8::TryCatch try_catch; date_t d1, d2; d1.now(); v8::Local<v8::Function>::New(isolate, p1->m_block)->Call(v8::Undefined(isolate), 0, NULL); d2.now(); if (try_catch.HasCaught()) { sprintf(buf, "%d) ", ++errcnt); p1->m_error = true; if (loglevel > console_base::_ERROR) ReportException(try_catch, 0); else if (loglevel == console_base::_ERROR) { std::string str1(buf); for (i = 1; i < (int)stack.size(); i ++) { str1.append(stack[i]->m_name); str1.append(" ", 1); } str1.append(p1->m_name); names.append(logger::highLight() + str1 + COLOR_RESET); msgs.append(GetException(try_catch, 0)); } str.append(buf); str.append(p1->m_name); } else { double n = d2.diff(d1); str.append(logger::notice() + "\xe2\x88\x9a " COLOR_RESET); str.append(p1->m_name); if (n > s_slow / 2) { sprintf(buf, " (%dms) ", (int) n); if (n > s_slow) str.append(logger::error()); else str.append(logger::warn()); str.append(buf); str.append(COLOR_RESET); } } } console_base::set_loglevel(oldlevel); asyncLog( p1->m_error ? console_base::_ERROR : console_base::_INFO, str); console_base::set_loglevel(loglevel); for (j = (int) stack.size() - 1; j >= 0; j--) { p2 = stack[j]; for (i = (int) p2->m_hooks[HOOK_AFTERCASE].size() - 1; i >= 0; i--) if (v8::Local<v8::Function>::New(isolate, p2->m_hooks[HOOK_AFTERCASE][i])->Call(v8::Undefined(isolate), 0, NULL).IsEmpty()) { console_base::set_loglevel(oldlevel); clear(); return 0; } } } if (p->m_pos == (int)p->m_subs.size()) { for (i = (int) p->m_hooks[HOOK_AFTER].size() - 1; i >= 0; i--) if (v8::Local<v8::Function>::New(isolate, p->m_hooks[HOOK_AFTER][i])->Call(v8::Undefined(isolate), 0, NULL).IsEmpty()) { console_base::set_loglevel(oldlevel); clear(); return 0; } stack.pop(); } } console_base::set_loglevel(oldlevel); asyncLog(console_base::_INFO, ""); if (errcnt == 0) { da2.now(); sprintf(buf, (logger::notice() + " \xe2\x88\x9a %d tests completed" COLOR_RESET " (%dms)").c_str(), cnt, (int) da2.diff(da1)); asyncLog(console_base::_INFO, buf); } else { sprintf(buf, (logger::error() + " × %d of %d tests failed" COLOR_RESET).c_str(), errcnt, cnt); asyncLog(console_base::_ERROR, buf); } asyncLog(console_base::_INFO, ""); for (i = 0; i < (int) msgs.size(); i++) { asyncLog(console_base::_INFO, names[i]); asyncLog(console_base::_ERROR, msgs[i]); } clear(); return 0; }
std::string json_format(v8::Local<v8::Value> obj) { StringBuffer strBuffer; Isolate* isolate = Isolate::current(); QuickArray<_item> stk; QuickArray<v8::Local<v8::Object>> vals; v8::Local<v8::Value> v = obj; v8::Local<v8::String> mark_name = isolate->NewFromUtf8("_util_format_mark"); int32_t padding = 0; const int32_t tab_size = 2; _item *it = NULL; while (true) { if (v.IsEmpty()) strBuffer.append("undefined"); else if (v->IsUndefined() || v->IsNull() || v->IsDate() || v->IsBoolean() || v->IsBooleanObject()) strBuffer.append(*v8::String::Utf8Value(v)); else if (v->IsNumber() || v->IsNumberObject()) strBuffer.append(*v8::String::Utf8Value(v->ToNumber())); else if (v->IsString() || v->IsStringObject()) string_format(strBuffer, v); else if (v->IsRegExp()) { v8::Local<v8::RegExp> re = v8::Local<v8::RegExp>::Cast(v); v8::Local<v8::String> src = re->GetSource(); v8::RegExp::Flags flgs = re->GetFlags(); strBuffer.append('/'); strBuffer.append(*v8::String::Utf8Value(src)); strBuffer.append('/'); if (flgs & v8::RegExp::kIgnoreCase) strBuffer.append('i'); if (flgs & v8::RegExp::kGlobal) strBuffer.append('g'); if (flgs & v8::RegExp::kMultiline) strBuffer.append('m'); } else if (v->IsObject()) { do { v8::Local<v8::Object> obj = v->ToObject(); v8::Local<v8::Array> keys = obj->GetPropertyNames(); if (v->IsFunction() && keys->Length() == 0) { strBuffer.append("[Function]"); break; } obj_ptr<Buffer_base> buf = Buffer_base::getInstance(v); if (buf) { static char hexs[] = "0123456789abcdef"; std::string data; std::string s; int32_t len, i; buf->toString(data); len = (int32_t)data.length(); s.resize(len * 3 + 8); memcpy(&s[0], "<Buffer", 7); for (i = 0; i < len; i ++) { int32_t ch = (unsigned char)data[i]; s[i * 3 + 7] = ' '; s[i * 3 + 8] = hexs[ch >> 4]; s[i * 3 + 9] = hexs[ch & 0xf]; } s[i * 3 + 7] = '>'; strBuffer.append(s); break; } obj_ptr<Int64_base> int64Val = Int64_base::getInstance(v); if (int64Val) { std::string s; int64Val->toString(10, s); strBuffer.append(s); break; } v8::Local<v8::Value> mk = obj->GetHiddenValue(mark_name); if (!mk.IsEmpty()) { strBuffer.append("[Circular]"); break; } vals.append(obj); obj->SetHiddenValue(mark_name, obj); v8::Local<v8::Value> toArray = obj->Get(isolate->NewFromUtf8("toArray")); if (!IsEmpty(toArray) && toArray->IsFunction()) { v = v8::Local<v8::Function>::Cast(toArray)->Call(obj, 0, NULL); obj = v->ToObject(); } int32_t sz = (int32_t)stk.size(); if (v->IsArray()) { v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(v); int32_t len = array->Length(); if (len == 0) strBuffer.append("[]"); else { if (len == 1 && v->StrictEquals(array->Get(0))) strBuffer.append("[Circular]"); else { stk.resize(sz + 1); it = &stk[sz]; it->val = v; it->keys = array; it->len = len; strBuffer.append('['); padding += tab_size; } } break; } int32_t len = keys->Length(); if (len == 0) strBuffer.append("{}"); else { if (len == 1 && v->StrictEquals(obj->Get(keys->Get(0)))) strBuffer.append("[Circular]"); else { stk.resize(sz + 1); it = &stk[sz]; it->val = v; it->obj = obj; it->keys = keys; it->len = len; strBuffer.append('{'); padding += tab_size; } } } while (false); } if (it) { while (it && it->pos == it->len) { padding -= tab_size; newline(strBuffer, padding); strBuffer.append(it->obj.IsEmpty() ? ']' : '}'); int32_t sz = (int32_t)stk.size(); stk.resize(sz - 1); if (sz > 1) it = &stk[sz - 2]; else it = NULL; } if (!it) break; if (it->pos) strBuffer.append(','); newline(strBuffer, padding); v = it->keys->Get(it->pos ++); if (!it->obj.IsEmpty()) { TryCatch try_catch; string_format(strBuffer, v); strBuffer.append(": "); v = it->obj->Get(v); } } else break; } int32_t sz1 = (int32_t)vals.size(); int32_t i; for (i = 0; i < sz1; i ++) vals[i]->DeleteHiddenValue(mark_name); return strBuffer.str(); }
result_t X509Cert::load(exlib::string txtCert) { if (m_root) return CHECK_ERROR(CALL_E_INVALID_CALL); int32_t ret; if (qstrstr(txtCert.c_str(), "BEGIN CERTIFICATE")) { ret = mbedtls_x509_crt_parse(&m_crt, (const unsigned char *)txtCert.c_str(), txtCert.length() + 1); if (ret != 0) return CHECK_ERROR(_ssl::setError(ret)); return 0; } _parser p(txtCert); QuickArray<std::pair<exlib::string, exlib::string> > values; std::map<exlib::string, bool> verifies; std::map<exlib::string, bool> certs; while (!p.end()) { exlib::string cka_label; exlib::string cka_value; exlib::string cka_serial; exlib::string _value; bool in_multiline = false, in_obj = false; bool is_cert = false; bool is_trust = false; bool is_value = false; bool is_serial = false; bool is_ca = false; bool is_verify = false; while (!p.end()) { exlib::string line; exlib::string cmd, type, value; p.getLine(line); _parser p1(line); p1.skipSpace(); if (p1.get() == '#') continue; if (in_multiline) { if (p1.get() == '\\') { while (p1.get() == '\\') { char ch1, ch2, ch3; p1.skip(); ch1 = p1.getChar(); if (ch1 < '0' || ch1 > '7') break; ch2 = p1.getChar(); if (ch2 < '0' || ch2 > '7') break; ch3 = p1.getChar(); if (ch3 < '0' || ch3 > '7') break; ch1 = (ch1 - '0') * 64 + (ch2 - '0') * 8 + (ch3 - '0'); _value.append(&ch1, 1); } continue; } p1.getWord(cmd); if ((cmd == "END")) { if (is_value) cka_value = _value; else if (is_serial) cka_serial = _value; in_multiline = false; } continue; } p1.getWord(cmd); p1.skipSpace(); p1.getWord(type); if ((type == "MULTILINE_OCTAL")) { in_multiline = true; _value.resize(0); is_value = is_cert && (cmd == "CKA_VALUE"); is_serial = (cmd == "CKA_SERIAL_NUMBER"); continue; } p1.skipSpace(); p1.getLeft(value); if (!in_obj) { if ((cmd == "CKA_CLASS")) { in_obj = true; is_cert = (value == "CKO_CERTIFICATE"); is_trust = (value == "CKO_NSS_TRUST"); } continue; } if ((cmd == "CKA_LABEL")) cka_label = value; else if (is_trust && (cmd == "CKA_TRUST_SERVER_AUTH")) { is_ca = (value == "CKT_NSS_TRUSTED_DELEGATOR"); is_verify = (value == "CKT_NSS_MUST_VERIFY_TRUST"); } if (cmd.empty()) break; } if (!cka_label.empty()) { if (is_trust) { if (is_ca) certs.insert(std::pair<exlib::string, bool>(cka_label + cka_serial, true)); if (is_verify) verifies.insert(std::pair<exlib::string, bool>(cka_label + cka_serial, true)); } else if (is_cert && !cka_value.empty()) values.append(std::pair<exlib::string, exlib::string>(cka_label + cka_serial, cka_value)); } } bool is_loaded = false; int32_t i; for (i = 0; i < (int32_t)values.size(); i++) { std::pair<exlib::string, exlib::string> &c = values[i]; std::map<exlib::string, bool>::iterator it_trust; it_trust = verifies.find(c.first); if (it_trust != verifies.end()) { ret = mbedtls_x509_crt_parse_der(&m_crt, (const unsigned char *)c.second.c_str(), c.second.length()); if (ret != 0) return CHECK_ERROR(_ssl::setError(ret)); is_loaded = true; } } for (i = 0; i < (int32_t)values.size(); i++) { std::pair<exlib::string, exlib::string> &c = values[i]; std::map<exlib::string, bool>::iterator it_trust; it_trust = certs.find(c.first); if (it_trust != certs.end()) { ret = mbedtls_x509_crt_parse_der(&m_crt, (const unsigned char *)c.second.c_str(), c.second.length() ); if (ret != 0) return CHECK_ERROR(_ssl::setError(ret)); is_loaded = true; } } if (!is_loaded) return CHECK_ERROR(_ssl::setError(MBEDTLS_ERR_X509_INVALID_FORMAT)); return 0; }