bool generateOutTuple(std::vector<std::string> &s, lindaTuple &newTuple, VarMap &localVars, FunctSet &userDefinedFuncs, LoopMap &loopSymbols, int threadNum) { for (std::vector<std::string>::iterator it = s.begin(); it != s.end(); it++) { if (isExp(*it)) { int result = evaluateExp(*it, loopSymbols, userDefinedFuncs, localVars, threadNum); if (result != -1) { newTuple.push_back(new intObj(result)); } else { // wait and block } } else if (isVarPattern(*it)) { if (localVars.find(*it) != localVars.end()) { newTuple.push_back(localVars[*it]); } else { std::cout<< "Can not find local var " << *it << std::endl; return false; } } else if (isString(*it)) newTuple.push_back(new stringObj(*it)); else if (isInt(*it)) newTuple.push_back(new intObj(atoi(it->c_str()))); else if (isDouble(*it)) newTuple.push_back(new doubleObj(atof(it->c_str()))); else { std::cout << "Parse input error: " << *it << std::endl; exit(EXIT_FAILURE); } } return true; }
Test::Result run_one_test(const std::string&, const VarMap& vars) override { Test::Result result("OCB wide block KAT"); const std::vector<uint8_t> key = vars.get_req_bin("Key"); const std::vector<uint8_t> nonce = vars.get_req_bin("Nonce"); const std::vector<uint8_t> ad = vars.get_req_bin("AD"); const std::vector<uint8_t> input = vars.get_req_bin("In"); const std::vector<uint8_t> expected = vars.get_req_bin("Out"); const size_t bs = key.size(); Botan::secure_vector<uint8_t> buf(input.begin(), input.end()); Botan::OCB_Encryption enc(new OCB_Wide_Test_Block_Cipher(bs), std::min<size_t>(bs, 32)); enc.set_key(key); enc.set_ad(ad); enc.start(nonce); enc.finish(buf); result.test_eq("Ciphertext matches", buf, expected); Botan::OCB_Decryption dec(new OCB_Wide_Test_Block_Cipher(bs), std::min<size_t>(bs, 32)); dec.set_key(key); dec.set_ad(ad); dec.start(nonce); dec.finish(buf); result.test_eq("Decryption correct", buf, input); return result; }
ACCExpr *cleanupBool(ACCExpr *expr) { if (!expr) return expr; inBool++; // can be invoked recursively! walkReplaceBuiltin(expr); inBool--; int varIndex = 0; VarMap varMap; DdManager * mgr = Cudd_Init(MAX_NAME_COUNT,0,CUDD_UNIQUE_SLOTS,CUDD_CACHE_SLOTS,0); varIndex = 0; varMap.clear(); DdNode *bdd = tree2BDD(mgr, expr, varMap); char const *inames[MAX_NAME_COUNT]; for (auto item: varMap) inames[item.second->index] = strdup(item.first.c_str()); char * fform = Cudd_FactoredFormString(mgr, bdd, inames); Cudd_RecursiveDeref(mgr, bdd); int err = Cudd_CheckZeroRef(mgr); if (trace_bool) printf("%s: expr '%s' val = %s\n", __FUNCTION__, tree2str(expr).c_str(), fform); assert(err == 0 && "Reference counting"); ACCExpr *ret = str2tree(fform); free(fform); Cudd_Quit(mgr); return ret; }
void TestSlice2(const VarMap& mp){ for(VarMap::const_iterator vmIt = mp.begin(); vmIt != mp.end(); ++vmIt){ std::cerr<<"-------------------------"<<std::endl; std::cerr<<"Variable: "<<vmIt->first<<std::endl; std::cerr<<"Slines: {"; for(unsigned int sl : vmIt->second.slines){ std::cerr<<sl<<","; } std::cerr<<"}"<<std::endl; std::cerr<<"dvars: {"; for(std::string dv : vmIt->second.dvars){ std::cerr<<dv<<","; } std::cerr<<"}"<<std::endl; std::cerr<<"is aliase for: {"; for(std::string al : vmIt->second.aliases){ std::cerr<<al<<","; } std::cerr<<"}"<<std::endl; std::cerr<<"cfuntions: {"; for(auto cfunc : vmIt->second.cfunctions){ std::cerr<<cfunc.first<<" "<<cfunc.second<<","; } std::cerr<<"}"<<std::endl; std::cerr<<"-------------------------"<<std::endl; } }
void get_var(Pu *L, const PuString &name, __pu_value *&v) { VarMap *pvarmap = L->varstack.top(); VarMap::Bucket_T *ik = pvarmap->find(name); if (ik != 0) { v = &ik->value; return; } pvarmap = L->varstack.bottom(); ik = pvarmap->find(name); if (ik != 0) { v = &ik->value; return; } if (L->upvalue && L->upvalue != pvarmap) { pvarmap = L->upvalue; ik = pvarmap->find(name); if (ik != 0) { v = &ik->value; return; } } MAKE_TEMP_VALUE(v); error(L,7); }
AstVarScope* createVarSc(AstVarScope* oldvarscp, string name, int width/*0==fromoldvar*/) { // Because we've already scoped it, we may need to add both the AstVar and the AstVarScope if (!oldvarscp->scopep()) oldvarscp->v3fatalSrc("Var unscoped"); AstVar* varp; AstNodeModule* addmodp = oldvarscp->scopep()->modp(); // We need a new AstVar, but only one for all scopes, to match the new AstVarScope VarMap::iterator iter = m_modVarMap.find(make_pair(addmodp,name)); if (iter != m_modVarMap.end()) { // Created module's AstVar earlier under some other scope varp = iter->second; } else { if (width==0) { varp = new AstVar (oldvarscp->fileline(), AstVarType::BLOCKTEMP, name, oldvarscp->varp()); varp->widthSignedFrom(oldvarscp); } else { // Used for vset and dimensions, so can zero init varp = new AstVar (oldvarscp->fileline(), AstVarType::BLOCKTEMP, name, AstBitPacked(), width); } addmodp->addStmtp(varp); m_modVarMap.insert(make_pair(make_pair(addmodp, name), varp)); } AstVarScope* varscp = new AstVarScope (oldvarscp->fileline(), oldvarscp->scopep(), varp); oldvarscp->scopep()->addVarp(varscp); return varscp; }
QString DownloadQueue::getCID(const VarMap &map){ if (map.size() < 1) return ""; auto it = map.constBegin(); return (it.value()).toString(); }
void ClientOptions::insertVarMapIntoDOM(ticpp::Element* parent, const VarMap &vars) { for (VarMap::const_iterator it = vars.begin(), end = vars.end(); it != end; ++it) { ticpp::Element* var = new ticpp::Element("var"); var->SetAttribute("name", it->first.c_str()); var->SetAttribute("value", it->second.c_str()); parent->LinkEndChild( var ); } }
//================================================================================= /*virtual*/ Node::ValueStringError BoundedPointListNode::SetValueFromString( const std::string& valueString ) { VarMap varMap; if( !ConvertValueStringToVarMap( valueString, varMap ) ) return VSE_SYNTAX; Bounds trialBounds = bounds; if( varMap.end() != varMap.find( "xMin" ) ) trialBounds.min.set_e1( varMap[ "xMin" ] ); if( varMap.end() != varMap.find( "xMax" ) ) trialBounds.max.set_e1( varMap[ "xMax" ] ); if( varMap.end() != varMap.find( "yMin" ) ) trialBounds.min.set_e2( varMap[ "yMin" ] ); if( varMap.end() != varMap.find( "yMax" ) ) trialBounds.max.set_e2( varMap[ "yMax" ] ); if( trialBounds == bounds ) return VSE_NO_CHANGE; if( !trialBounds.IsValid() ) return VSE_INVALID; if( !SetBounds( trialBounds ) ) return VSE_INVALID; return VSE_NONE; }
//================================================================================= /*virtual*/ Node::ValueStringError BoundedIntegerNode::SetValueFromString( const std::string& valueString ) { VarMap varMap; if( !ConvertValueStringToVarMap( valueString, varMap ) ) return VSE_SYNTAX; Data trialData = data; if( varMap.end() != varMap.find( "min" ) ) trialData.min = int( varMap[ "min" ] ); if( varMap.end() != varMap.find( "max" ) ) trialData.max = int( varMap[ "max" ] ); if( varMap.end() != varMap.find( "value" ) ) trialData.value = int( varMap[ "value" ] ); if( varMap.end() != varMap.find( "multiple" ) ) trialData.multiple = int( varMap[ "multiple" ] ); if( !trialData.IsValid() ) return VSE_INVALID; if( trialData == data ) return VSE_NO_CHANGE; data = trialData; return VSE_NONE; }
Test::Result run_one_test(const std::string&, const VarMap& vars) override { const std::vector<uint8_t> record = vars.get_req_bin("Record"); const size_t output = vars.get_req_sz("Output"); uint16_t res = Botan::TLS::check_tls_cbc_padding(record.data(), record.size()); Test::Result result("TLS CBC padding check"); result.test_eq("Expected", res, output); return result; }
Test::Result run_one_test(const std::string&, const VarMap& vars) override { const size_t keylen = vars.get_req_sz("Keylen"); const size_t taglen = vars.get_req_sz("Taglen"); const std::vector<uint8_t> expected = vars.get_req_bin("Output"); // Test from RFC 7253 Appendix A const std::string algo = "AES-" + std::to_string(keylen); Test::Result result("OCB long"); std::unique_ptr<Botan::BlockCipher> aes(Botan::BlockCipher::create(algo)); if(!aes) { result.note_missing(algo); return result; } Botan::OCB_Encryption enc(aes->clone(), taglen / 8); Botan::OCB_Decryption dec(aes->clone(), taglen / 8); std::vector<uint8_t> key(keylen / 8); key[keylen / 8 - 1] = static_cast<uint8_t>(taglen); enc.set_key(key); dec.set_key(key); const std::vector<uint8_t> empty; std::vector<uint8_t> N(12); std::vector<uint8_t> C; for(size_t i = 0; i != 128; ++i) { const std::vector<uint8_t> S(i); Botan::store_be(static_cast<uint32_t>(3 * i + 1), &N[8]); ocb_encrypt(result, C, enc, dec, N, S, S); Botan::store_be(static_cast<uint32_t>(3 * i + 2), &N[8]); ocb_encrypt(result, C, enc, dec, N, S, empty); Botan::store_be(static_cast<uint32_t>(3 * i + 3), &N[8]); ocb_encrypt(result, C, enc, dec, N, empty, S); } Botan::store_be(static_cast<uint32_t>(385), &N[8]); std::vector<uint8_t> final_result; ocb_encrypt(result, final_result, enc, dec, N, empty, C); result.test_eq("correct value", final_result, expected); return result; }
Test::Result PK_Signature_Generation_Test::run_one_test(const std::string&, const VarMap& vars) { const std::vector<uint8_t> message = get_req_bin(vars, "Msg"); const std::vector<uint8_t> signature = get_req_bin(vars, "Signature"); const std::string padding = get_opt_str(vars, "Padding", default_padding(vars)); std::unique_ptr<Botan::RandomNumberGenerator> rng; if(vars.count("Nonce")) { rng.reset(new Fixed_Output_RNG(get_req_bin(vars, "Nonce"))); } Test::Result result(algo_name() + "/" + padding + " signature generation"); std::unique_ptr<Botan::Private_Key> privkey = load_private_key(vars); std::unique_ptr<Botan::Public_Key> pubkey(Botan::X509::load_key(Botan::X509::BER_encode(*privkey))); Botan::PK_Signer signer(*privkey, padding); Botan::PK_Verifier verifier(*pubkey, padding); const std::vector<uint8_t> generated_signature = signer.sign_message(message, rng ? *rng : Test::rng()); result.test_eq("generated signature matches KAT", generated_signature, signature); result.test_eq("generated signature valid", verifier.verify_message(message, generated_signature), true); check_invalid_signatures(result, verifier, message, signature); result.test_eq("correct signature valid", verifier.verify_message(message, signature), true); return result; }
Test::Result PK_Encryption_Decryption_Test::run_one_test(const std::string&, const VarMap& vars) { const std::vector<uint8_t> plaintext = get_req_bin(vars, "Msg"); const std::vector<uint8_t> ciphertext = get_req_bin(vars, "Ciphertext"); const std::string padding = get_opt_str(vars, "Padding", default_padding(vars)); std::unique_ptr<Botan::RandomNumberGenerator> kat_rng; if(vars.count("Nonce")) { kat_rng.reset(new Fixed_Output_RNG(get_req_bin(vars, "Nonce"))); } Test::Result result(algo_name() + "/" + padding + " decryption"); std::unique_ptr<Botan::Private_Key> privkey = load_private_key(vars); // instead slice the private key to work around elgamal test inputs //std::unique_ptr<Botan::Public_Key> pubkey(Botan::X509::load_key(Botan::X509::BER_encode(*privkey))); Botan::PK_Encryptor_EME encryptor(*privkey, padding); result.test_eq("encryption", encryptor.encrypt(plaintext, kat_rng ? *kat_rng : Test::rng()), ciphertext); Botan::PK_Decryptor_EME decryptor(*privkey, padding); result.test_eq("decryption", decryptor.decrypt(ciphertext), plaintext); check_invalid_ciphertexts(result, decryptor, plaintext, ciphertext); return result; }
//================================================================================= /*static*/ bool Node::ConvertValueStringFromVarMap( std::string& valueString, const VarMap& varMap ) { valueString = ""; for( VarMap::const_iterator iter = varMap.begin(); iter != varMap.end(); iter++ ) { std::string key = iter->first; double numericalValue = iter->second; std::ostringstream stream; stream << numericalValue; std::string value = stream.str(); if( !valueString.empty() ) valueString += ", "; valueString += key + "=" + value; } return true; }
virtual void visit(AstVarRef* nodep, AstNUser*) { if (nodep->lvalue() && !nodep->user2()) { nodep->user2(true); // mark this ref as visited AstVar* key = nodep->varp(); VarMap::iterator it = m_lhsmapp->find(key); if (it == m_lhsmapp->end()) { // this key does not exist yet, so create it RefVec* refs = new RefVec(); refs->push_back(nodep); m_lhsmapp->insert(pair<AstVar*, RefVec*>(key, refs)); } else { (*it).second->push_back(nodep); } nodep->user3p(m_sel); // attach the sel to this varref } nodep->iterateChildren(*this); }
static __pu_value *get_varref(Pu *L, PuString &name) { VarMap *pvarmap = L->varstack.top(); VarMap::Bucket_T *ik = pvarmap->find(name); if (ik != 0) { return &(ik->value); } pvarmap = L->varstack.bottom(); ik = pvarmap->find(name); if (ik != 0) { return &(ik->value); } return NULL; }
Test::Result run_one_test(const std::string&, const VarMap& vars) override { Test::Result result("TLS CBC"); const size_t block_size = vars.get_req_sz("Blocksize"); const size_t mac_len = vars.get_req_sz("MACsize"); const std::vector<uint8_t> record = vars.get_req_bin("Record"); const bool is_valid = vars.get_req_sz("Valid") == 1; // todo test permutations bool encrypt_then_mac = false; Botan::TLS::TLS_CBC_HMAC_AEAD_Decryption tls_cbc( std::unique_ptr<Botan::BlockCipher>(new Noop_Block_Cipher(block_size)), std::unique_ptr<Botan::MessageAuthenticationCode>(new ZeroMac(mac_len)), 0, 0, Botan::TLS::Protocol_Version::TLS_V11, encrypt_then_mac); tls_cbc.set_key(std::vector<uint8_t>(0)); std::vector<uint8_t> ad(13); tls_cbc.set_associated_data(ad.data(), ad.size()); Botan::secure_vector<uint8_t> vec(record.begin(), record.end()); try { tls_cbc.finish(vec, 0); if(is_valid) result.test_success("Accepted valid TLS-CBC ciphertext"); else result.test_failure("Accepted invalid TLS-CBC ciphertext"); } catch(std::exception&) { if(is_valid) result.test_failure("Rejected valid TLS-CBC ciphertext"); else result.test_success("Accepted invalid TLS-CBC ciphertext"); } return result; }
Test::Result run_one_test(const std::string& algo, const VarMap& vars) override { Test::Result result(algo + " Decoding"); std::unique_ptr<Botan::EME> eme; try { eme.reset(Botan::get_eme(algo)); } catch(Botan::Lookup_Error&) { result.note_missing(algo); return result; } const std::vector<uint8_t> ciphertext = vars.get_req_bin("RawCiphertext"); const std::vector<uint8_t> plaintext = vars.get_opt_bin("Plaintext"); const bool is_valid = vars.get_req_bool("ValidInput"); if(is_valid == false) { result.test_eq("Plaintext value is empty for invalid EME inputs", plaintext.size(), 0); } uint8_t valid_mask = 0; Botan::secure_vector<uint8_t> decoded = eme->unpad(valid_mask, ciphertext.data(), ciphertext.size()); result.confirm("EME valid_mask has expected value", valid_mask == 0x00 || valid_mask == 0xFF); result.test_eq("EME decoding valid/invalid matches", valid_mask == 0xFF, is_valid); if(is_valid && valid_mask == 0xFF) { result.test_eq("EME decoded plaintext correct", decoded, plaintext); } // TODO: also test that encoding is accepted return result; }
int evaluateExp(std::string expr, LoopMap &loopSymbols, FunctSet &userDefinedFuncs, VarMap &localVars, int threadNum) { int result = -1; std::string expName = (expr).substr(0, (expr).find("(")); std::string expNameT = expName + std::to_string(static_cast<long long int>(threadNum)); size_t start = (expr).find("(") + 1; size_t end = (expr).find_last_of(")"); std::string params = (expr).substr(start, end - start); if (userDefinedFuncs.find(expNameT) != userDefinedFuncs.end()) { // Case 1: The expression is a user defined function if (!isInt(params)) { if (loopSymbols.find(params) != loopSymbols.end()) { params = std::to_string(static_cast<long long int>(loopSymbols[params])); } else if (localVars.find(params) != localVars.end()) { intObj *intO = dynamic_cast<intObj *>(localVars[params]); params = std::to_string(static_cast<long long int>(intO->get())); } } int status = system(("./" + expNameT + " " + params).c_str()); result = WEXITSTATUS(status); } else { // Case 2: The expression is inp or rdp //std::cout << "condition is " << expr << std::endl; LINDA_TYPE type = findFunctionType(expr); //std::cout << "expr type is " << type << std::endl; std::vector<std::string> elems; if (type == INP) { getInOutElems(expr, elems); return inp(elems, localVars, userDefinedFuncs, loopSymbols, threadNum); } else if (type == RDP) { getInOutElems(expr, elems); return rdp(elems, localVars, userDefinedFuncs, loopSymbols, threadNum); } else { std::cout << "Couldn't evaluate expression " << expr << std::endl; std::cout << "No boolean return type or couldn't find expr name" << std::endl; exit(EXIT_FAILURE); } } return result; }
__pu_value *reg_var(Pu *L, const PuString &varname) { __pu_value *got = NULL; VarMap *varmap = L->varstack.top(); VarMap::Bucket_T *it = varmap->find(varname); if (it != 0) { got = &(it->value); } else { VarMap *varmap = L->varstack.bottom(); VarMap::Bucket_T *it = varmap->find(varname); if (it != 0) { got = &(it->value); } } if (got == NULL) { VarMap *varmap = L->varstack.top(); VarMap::Bucket_T *ret = varmap->insert(varname, __pu_value(L)); got = &(ret->value); } return got; }
//================================================================================= /*virtual*/ Node::ValueStringError ConeNode::SetValueFromString( const std::string& valueString ) { ValueStringError vse = VectorE3GANode::SetValueFromString( valueString ); if( !( vse == VSE_NONE || vse == VSE_NO_CHANGE ) ) return vse; VarMap varMap; if( !ConvertValueStringToVarMap( valueString, varMap ) ) return VSE_SYNTAX; double trialConeAngle = coneAngle; if( varMap.end() != varMap.find( "coneAngle" ) ) trialConeAngle = varMap[ "coneAngle" ]; if( trialConeAngle < 0.0 || trialConeAngle > M_PI ) return VSE_INVALID; if( trialConeAngle == coneAngle && vse == VSE_NO_CHANGE ) return VSE_NO_CHANGE; coneAngle = trialConeAngle; return VSE_NONE; }
//================================================================================= /*virtual*/ Node::ValueStringError BivectorE3GANode::SetValueFromString( const std::string& valueString ) { VarMap varMap; if( !ConvertValueStringToVarMap( valueString, varMap ) ) return VSE_SYNTAX; // Get the new bivector. c3ga::bivectorE3GA trialBivector = *bivector; if( varMap.end() != varMap.find( "yz" ) ) trialBivector.set_e2_e3( varMap[ "yz" ] ); if( varMap.end() != varMap.find( "zx" ) ) trialBivector.set_e3_e1( varMap[ "zx" ] ); if( varMap.end() != varMap.find( "xy" ) ) trialBivector.set_e1_e2( varMap[ "xy" ] ); // Validate the new bivector. if( c3ga::norm( trialBivector ) > maxArea ) return VSE_INVALID; // Get the new max-area. double trialMaxArea = maxArea; if( varMap.end() != varMap.find( "maxArea" ) ) trialMaxArea = varMap[ "maxArea" ]; // Validate the new max-area. if( trialMaxArea <= 0.0 ) return VSE_INVALID; // Reject if no change occurred. if( c3ga::equals( trialBivector, *bivector, 0.0 ) && trialMaxArea == maxArea ) return VSE_NO_CHANGE; // Accept the new values. *bivector = trialBivector; maxArea = trialMaxArea; return VSE_NONE; }
// TODO: оптимизировать! RefChain* Session::substituteExpression(RefChain *chain){ if (chain->isEmpty()) { return new RefChain(this); //return chain; // в зависимости от того как сделана будет сборка мусора - раскомментировать строку выше } //std::cout << "\n" << chain->debug() << "\n\n" << std::flush; RefChain *result = new RefChain(this, chain->getLength()); RefVariable *tmpvar = 0; RefLinkToVariable *link = 0; RefDataBracket *brack = 0; RefPointLink *pointlink = 0; RefData **enditem = chain->at_afterlast(); for(RefData **item = chain->at_first(); item < enditem; ++item){ link = ref_dynamic_cast<RefLinkToVariable>(*item); // ССЫЛКА (ЗАКРЫТАЯ ПЕРЕМЕННАЯ) if (link){ RefData **endi, **i; RefChain *i_chain; VarMap* vm = 0; if (! findVar(link->getLnk(), i, endi, i_chain, vm)){ //std::cout << link->explode() << std::flush; std::cout << "\n\n" << this->debug() << "\n\n" << std::flush; SYSTEMERRORs(this, "Variable not found for link " + link->explode()); } if (link->getPath() != EmptyUniString){ // заглядывание в пользовательскую переменную if (! vm->folowByWay(link->getPath(), i, endi, i_chain, tmpvar, vm)) RUNTIMEERRORs(this, "Wrong way for variable " << link->getLnk()->toString() << " : " << link->getPath()); } if (i){ //*result += new RefChain(this, 0, i, endi); *result += new RefSegment(this, i_chain, i, endi); } continue; } brack = (*item)->isDataBracket(); // ДАТА-СКОБКИ if (brack){ if (ref_dynamic_cast<RefStructBrackets>(brack)){ *result += new RefStructBrackets(this, substituteExpression((RefChain*) brack->chain) ); //TODO: опасно! когда RefChainConstructor != RefChain } else { // RefExecBracket *result += new RefExecBrackets(this, substituteExpression((RefChain*) brack->chain) ); //TODO: опасно! когда RefChainConstructor != RefChain } continue; } pointlink = ref_dynamic_cast<RefPointLink>(*item); // ССЫЛКА-УКАЗАТЕЛЬ if (pointlink){ ref_assert(ref_dynamic_cast<RefVarChains>(pointlink->theLink->lnk)); RefData **ther=0, **thel=0; RefChain *thechain=0; VarMap* thevm = 0; if (! findVar(pointlink->theLink->getLnk(), thel, ther, thechain, thevm)){ std::cout << "\n\n" << this->debug() << "\n\n" << std::flush; SYSTEMERRORs(this, "Variable not found for &link " + pointlink->explode()); } if (pointlink->theLink->getPath() != EmptyUniString){ // заглядывание в пользовательскую переменную if (! thevm->folowByWay(pointlink->theLink->getPath(), thel, ther, thechain, tmpvar, thevm)){ RUNTIMEERRORs(this, "Wrong way for variable " << pointlink->theLink->getLnk()->toString() << " : " << pointlink->theLink->getPath()); } } else { tmpvar = pointlink->theLink->getLnk(); } /** *result += new RefPoint( ((RefVarChains*)pointlink->theLink->lnk)->getUserType(), thel, ther, thechain, thevm, this); */ RefVarChains *theType = ref_dynamic_cast<RefVarChains>(tmpvar); if (theType){ *result += new RefPoint( theType->getUserType(), thel, ther, thechain, thevm, this); } else { // определиться с семантикой языка: что делать с ссылками на значения НЕ пользовательского типа //*result += new RefChain(this, thechain, thel, ther); if (tmpvar!=0) { //RUNTIMEERRORs(this, "Can't create point to object-expression of non-user type: " << pointlink->debug() << " looks to " << (new RefChain(this, thechain, thel, ther))->debug() ); *result += new RefPoint( 0, thel, ther, thechain, thevm, this); }else{ unexpectedERRORs(this); } } continue; } *result += *item; } return result; }
Test::Result PK_Signature_Generation_Test::run_one_test(const std::string&, const VarMap& vars) { const std::vector<uint8_t> message = get_req_bin(vars, "Msg"); const std::vector<uint8_t> signature = get_req_bin(vars, "Signature"); const std::string padding = get_opt_str(vars, "Padding", default_padding(vars)); Test::Result result(algo_name() + "/" + padding + " signature generation"); std::unique_ptr<Botan::Private_Key> privkey = load_private_key(vars); std::unique_ptr<Botan::Public_Key> pubkey(Botan::X509::load_key(Botan::X509::BER_encode(*privkey))); for(auto&& sign_provider : possible_pk_providers()) { std::unique_ptr<Botan::PK_Signer> signer; try { signer.reset(new Botan::PK_Signer(*privkey, padding, Botan::IEEE_1363, sign_provider)); } catch(Botan::Lookup_Error&) { //result.test_note("Skipping signing with " + sign_provider); continue; } std::unique_ptr<Botan::RandomNumberGenerator> rng; if(vars.count("Nonce")) { rng.reset(new Fixed_Output_RNG(get_req_bin(vars, "Nonce"))); } const std::vector<uint8_t> generated_signature = signer->sign_message(message, rng ? *rng : Test::rng()); if(sign_provider == "base") { result.test_eq("generated signature matches KAT", generated_signature, signature); } for(auto&& verify_provider : possible_pk_providers()) { std::unique_ptr<Botan::PK_Verifier> verifier; try { verifier.reset(new Botan::PK_Verifier(*pubkey, padding, Botan::IEEE_1363, verify_provider)); } catch(Botan::Lookup_Error&) { //result.test_note("Skipping verifying with " + verify_provider); continue; } if(!result.test_eq("generated signature valid", verifier->verify_message(message, generated_signature), true)) { result.test_failure("generated signature", generated_signature); } check_invalid_signatures(result, *verifier, message, signature); result.test_eq("KAT signature valid", verifier->verify_message(message, signature), true); } } return result; }
Test::Result PK_Encryption_Decryption_Test::run_one_test(const std::string&, const VarMap& vars) { const std::vector<uint8_t> plaintext = get_req_bin(vars, "Msg"); const std::vector<uint8_t> ciphertext = get_req_bin(vars, "Ciphertext"); const std::string padding = get_opt_str(vars, "Padding", default_padding(vars)); Test::Result result(algo_name() + "/" + padding + " decryption"); std::unique_ptr<Botan::Private_Key> privkey = load_private_key(vars); // instead slice the private key to work around elgamal test inputs //std::unique_ptr<Botan::Public_Key> pubkey(Botan::X509::load_key(Botan::X509::BER_encode(*privkey))); Botan::Public_Key* pubkey = privkey.get(); for(auto&& enc_provider : possible_pk_providers()) { std::unique_ptr<Botan::PK_Encryptor> encryptor; try { encryptor.reset(new Botan::PK_Encryptor_EME(*pubkey, padding, enc_provider)); } catch(Botan::Lookup_Error&) { //result.test_note("Skipping encryption with provider " + enc_provider); continue; } std::unique_ptr<Botan::RandomNumberGenerator> kat_rng; if(vars.count("Nonce")) { kat_rng.reset(new Fixed_Output_RNG(get_req_bin(vars, "Nonce"))); } const std::vector<uint8_t> generated_ciphertext = encryptor->encrypt(plaintext, kat_rng ? *kat_rng : Test::rng()); if(enc_provider == "base") { result.test_eq("generated ciphertext matches KAT", generated_ciphertext, ciphertext); } for(auto&& dec_provider : possible_pk_providers()) { std::unique_ptr<Botan::PK_Decryptor> decryptor; try { decryptor.reset(new Botan::PK_Decryptor_EME(*privkey, padding, dec_provider)); } catch(Botan::Lookup_Error&) { //result.test_note("Skipping decryption with provider " + dec_provider); continue; } result.test_eq("decryption of KAT", decryptor->decrypt(ciphertext), plaintext); check_invalid_ciphertexts(result, *decryptor, plaintext, ciphertext); result.test_eq("decryption of generated ciphertext", decryptor->decrypt(generated_ciphertext), plaintext); } } return result; }
Error Context::livenessAnalysis() { FuncNode* func = getFunc(); JumpNode* from = NULL; Node* node = func->getEnd(); uint32_t bLen = static_cast<uint32_t>( ((_contextVd.getLength() + VarBits::kEntityBits - 1) / VarBits::kEntityBits)); LivenessTarget* ltCur = NULL; LivenessTarget* ltUnused = NULL; size_t varMapToVaListOffset = _varMapToVaListOffset; // No variables. if (bLen == 0) return kErrorOk; VarBits* bCur = newBits(bLen); if (bCur == NULL) goto _NoMemory; // Allocate bits for code visited first time. _OnVisit: for (;;) { if (node->hasLiveness()) { if (bCur->_addBitsDelSource(node->getLiveness(), bCur, bLen)) goto _OnPatch; else goto _OnDone; } VarBits* bTmp = copyBits(bCur, bLen); if (bTmp == NULL) goto _NoMemory; node->setLiveness(bTmp); VarMap* map = node->getMap(); if (map != NULL) { uint32_t vaCount = map->getVaCount(); VarAttr* vaList = reinterpret_cast<VarAttr*>(((uint8_t*)map) + varMapToVaListOffset); for (uint32_t i = 0; i < vaCount; i++) { VarAttr* va = &vaList[i]; VarData* vd = va->getVd(); uint32_t flags = va->getFlags(); uint32_t ctxId = vd->getContextId(); if ((flags & kVarAttrOutAll) && !(flags & kVarAttrInAll)) { // Write-Only. bTmp->setBit(ctxId); bCur->delBit(ctxId); } else { // Read-Only or Read/Write. bTmp->setBit(ctxId); bCur->setBit(ctxId); } } } if (node->getType() == kNodeTypeTarget) goto _OnTarget; if (node == func) goto _OnDone; ASMJIT_ASSERT(node->getPrev()); node = node->getPrev(); } // Patch already generated liveness bits. _OnPatch: for (;;) { ASMJIT_ASSERT(node->hasLiveness()); VarBits* bNode = node->getLiveness(); if (!bNode->_addBitsDelSource(bCur, bLen)) goto _OnDone; if (node->getType() == kNodeTypeTarget) goto _OnTarget; if (node == func) goto _OnDone; node = node->getPrev(); } _OnTarget: if (static_cast<TargetNode*>(node)->getNumRefs() != 0) { // Push a new LivenessTarget onto the stack if needed. if (ltCur == NULL || ltCur->node != node) { // Allocate a new LivenessTarget object (from pool or zone). LivenessTarget* ltTmp = ltUnused; if (ltTmp != NULL) { ltUnused = ltUnused->prev; } else { ltTmp = _baseZone.allocT<LivenessTarget>( sizeof(LivenessTarget) - sizeof(VarBits) + bLen * sizeof(uintptr_t)); if (ltTmp == NULL) goto _NoMemory; } // Initialize and make current - ltTmp->from will be set later on. ltTmp->prev = ltCur; ltTmp->node = static_cast<TargetNode*>(node); ltCur = ltTmp; from = static_cast<TargetNode*>(node)->getFrom(); ASMJIT_ASSERT(from != NULL); } else { from = ltCur->from; goto _OnJumpNext; } // Visit/Patch. do { ltCur->from = from; bCur->copyBits(node->getLiveness(), bLen); if (!from->hasLiveness()) { node = from; goto _OnVisit; } // Issue #25: Moved '_OnJumpNext' here since it's important to patch // code again if there are more live variables than before. _OnJumpNext: if (bCur->delBits(from->getLiveness(), bLen)) { node = from; goto _OnPatch; } from = from->getJumpNext(); } while (from != NULL); // Pop the current LivenessTarget from the stack. { LivenessTarget* ltTmp = ltCur; ltCur = ltCur->prev; ltTmp->prev = ltUnused; ltUnused = ltTmp; } } bCur->copyBits(node->getLiveness(), bLen); node = node->getPrev(); if (node->isJmp() || !node->isFetched()) goto _OnDone; if (!node->hasLiveness()) goto _OnVisit; if (bCur->delBits(node->getLiveness(), bLen)) goto _OnPatch; _OnDone: if (ltCur != NULL) { node = ltCur->node; from = ltCur->from; goto _OnJumpNext; } return kErrorOk; _NoMemory: return setError(kErrorNoHeapMemory); }
virtual void visit(AstNodeModule* nodep, AstNUser*) { UINFO(9," MOD "<<nodep<<endl); m_unique = 0; VarMap* lhsmapp = new VarMap(); // expand tristate nodes and detect multiple LHS drivers for this module TristateExpander(nodep, lhsmapp); // iterate the children to grab any __en signals from subcells m_modp = nodep; nodep->iterateChildren(*this); m_modp = NULL; // go through each multiple lhs driver & collapse it to a single driver for (VarMap::iterator nextit, it=lhsmapp->begin(); it != lhsmapp->end(); it=nextit) { nextit = it; ++nextit; m_unique = 0; AstVar* lhsp = (*it).first; RefVec* refs = (*it).second; bool isOutput = (lhsp->varType() == AstVarType::OUTPUT) && (nodep->level() > 1); // force termination at top level if (refs->size() < 2 && isOutput) { // if only one driver and this is an output, then exit and // let the driver propagate on its own. If the signals // terminates at this level, then we need to let the // undriven state get generated. lhsmapp->erase(lhsp); delete refs; continue; } UINFO(9, " Checking " << refs->size() << " drivers for tristates signals on net " << lhsp << endl); int pull = 0; // initially assume no pull direction // Now remove and multple lhs signals that do not have __en for // all possible drivers. bool complete = true; int found_one = 0; for (RefVec::iterator ii=refs->begin(); ii != refs->end(); ++ii) { AstVarRef* refp = (*ii); if (!refp->user1p()) { // if no __en signal, then delete the entry complete = false; } else { found_one++; } } if (!complete) { if (found_one) { UINFO(9, " Problem mixing tristate and low-Z on " << lhsp << endl); UINFO(9, " Found " << found_one << " __en signals from of " << refs->size() << " possible drivers" << endl); // not sure what I should do here other than error that they are mixing low-Z and tristate drivers. // The other scenerio, and probably more likely, is that they are using a high-Z construct that // is not supported. Improving the high-Z detection logic will reduce the occurance of this failure. nodep->v3error("Mixing tristate and low-Z drivers. Perhaps you are using a high-Z construct not supported"); } else { UINFO(9, " No tristates found on " << lhsp <<endl); } lhsmapp->erase(lhsp); delete refs; continue; } UINFO(9, " TRISTATE LHS DRIVER FOUND:" << lhsp << endl); AstNode* orp = NULL,* andp = NULL,* undrivenp = NULL,* newenlogicp = NULL; // loop through the lhs drivers to build the driver resolution logic for (RefVec::iterator ii=refs->begin(); ii != refs->end(); ++ii) { AstVarRef* refp = (*ii); int w = lhsp->width(); int wfill = 0; // width filler when necessary due to sels AstSel* selp = NULL; if (refp->user3p()) { // this varref has a sel selp = (AstSel*) refp->user3p(); w = selp->widthConst(); wfill = lhsp->width() - w; } // create a new var for this assignment. AstVar* enp = (AstVar*)refp->user1p(); AstVar* newlhsp = new AstVar(lhsp->fileline(), AstVarType::MODULETEMP, lhsp->name()+"__lhs"+cvtToStr(m_unique++), AstLogicPacked(), w); nodep->addStmtp(newlhsp); // now append this driver to the driver logic. AstNode* ref1 = new AstVarRef(nodep->fileline(), newlhsp,false); AstNode* ref2 = new AstVarRef(nodep->fileline(), enp, false); andp = new AstAnd(nodep->fileline(), ref1, ref2); AstVar* bitselp = NULL; if (selp) { // this varref has a sel int ws = V3Number::log2b(lhsp->width())+1; bitselp = new AstVar(lhsp->fileline(), AstVarType::MODULETEMP, lhsp->name()+"__sel"+cvtToStr(m_unique-1), AstLogicPacked(), ws); // nodep->addStmtp(bitselp); nodep->addStmtp(new AstAssignW(lhsp->fileline(), new AstVarRef(lhsp->fileline(), bitselp, true), selp->lsbp()->cloneTree(false))); andp = new AstShiftL(lhsp->fileline(), new AstConcat(lhsp->fileline(), new AstConst(lhsp->fileline(), V3Number(lhsp->fileline(), wfill, 0)), andp), new AstVarRef(lhsp->fileline(), bitselp, false), lhsp->width() ); selp->replaceWith(new AstVarRef(refp->fileline(), newlhsp, true)); pushDeletep(selp); // Setting selp here or deleting immediately // breaks the t_tri_select test, this probably indicates a problem } else { refp->varp(newlhsp); // assign the new var to the varref refp->name(newlhsp->name()); } // or this to the others orp = (!orp) ? andp : new AstOr(nodep->fileline(), orp, andp); if (isOutput) { AstNode *en1p = new AstVarRef(nodep->fileline(), enp, false); if (selp) { en1p = new AstShiftL(enp->fileline(), new AstConcat(lhsp->fileline(), new AstConst(lhsp->fileline(), V3Number(lhsp->fileline(), wfill, 0)), en1p), new AstVarRef(lhsp->fileline(), bitselp, false), lhsp->width() ); } if (!newenlogicp) { newenlogicp = en1p; } else { newenlogicp = new AstOr(nodep->fileline(), newenlogicp, en1p); } } else { if (!undrivenp) { undrivenp = new AstNot(nodep->fileline(), new AstVarRef(nodep->fileline(), enp, false)); if (selp) undrivenp = new AstShiftL(enp->fileline(), new AstConcat(lhsp->fileline(), new AstConst(lhsp->fileline(), V3Number(lhsp->fileline(), wfill, 0)), undrivenp), new AstVarRef(lhsp->fileline(), bitselp, false), lhsp->width()); } else { AstNode *tmp = new AstNot(nodep->fileline(), new AstVarRef(nodep->fileline(), enp, false)); if (selp) { tmp = new AstShiftL(enp->fileline(), new AstConcat(lhsp->fileline(), new AstConst(lhsp->fileline(), V3Number(lhsp->fileline(), wfill, 0)), tmp), new AstVarRef(lhsp->fileline(), bitselp, false), lhsp->width()); } undrivenp = new AstAnd(nodep->fileline(), tmp, undrivenp); } } refp->user1p(NULL); // clear the user1p() as we done with it in the VarRef at this point if (enp->user2()) { // if this net is pulled up/down int newpull = enp->user2(); if (pull == 0) { pull = newpull; } else if (newpull != pull) { pull = -1; // conflict over the pull direction } } } if (isOutput) { AstVar* newenp = new AstVar(lhsp->fileline(), AstVarType::OUTPUT, lhsp->name()+"__enout"+cvtToStr(m_unique++), lhsp); nodep->addStmtp(newenp); nodep->addStmtp(new AstAssignW(lhsp->fileline(), new AstVarRef(lhsp->fileline(), newenp, true), newenlogicp)); newenp->user2(pull); // put the pull direction in the next __en signal to pass it up lhsp->user1p(newenp); // put the new __en signal in the var so it can be pushed up the hierarchy. } else { // this is the level where the signal terminates, we do final conflict resolution here UINFO(9, " Terminating tristate logic for " << lhsp->name() << endl); UINFO(9, " Pull direction is " << pull << " where -1=X, 0=Z, 1=low, 2=high." << endl); // figure out what to drive when no one is driving the bus V3Number num(nodep->fileline(), lhsp->width()); if (pull==0) { num.setAllBitsZ(); } else if (pull==1) { num.setAllBits0(); } else if (pull==2) { num.setAllBits1(); } else { num.setAllBitsX(); } undrivenp = new AstAnd(nodep->fileline(), undrivenp, new AstConst(nodep->fileline(), num)); orp = new AstOr(nodep->fileline(), orp, undrivenp); } nodep->addStmtp(new AstAssignW(lhsp->fileline(), new AstVarRef(lhsp->fileline(), lhsp, true), orp)); // delete the map and vector list now that we have collapsed it. lhsmapp->erase(lhsp); delete refs; } delete lhsmapp; // delete the map now that we are done nodep->user1p(NULL); }
void DownloadQueue::slotContextMenu(const QPoint &){ QModelIndexList list = treeView_TARGET->selectionModel()->selectedRows(0); QList<DownloadQueueItem*> items; if (list.isEmpty()) return; getItems(list, items); if (items.isEmpty()) return; DownloadQueueItem *item = reinterpret_cast<DownloadQueueItem*>(items.at(0)); QString target = item->data(COLUMN_DOWNLOADQUEUE_PATH).toString() + item->data(COLUMN_DOWNLOADQUEUE_NAME).toString(); if (target.isEmpty()) return; Q_D(DownloadQueue); Menu::Action act = d->menu->exec(d->sources, target, items.size() > 1); QueueManager *QM = QueueManager::getInstance(); QVariant arg = d->menu->getArg(); VarMap rmap; /** Now re-read selected indexes and remove broken items */ list = treeView_TARGET->selectionModel()->selectedRows(0); getItems(list, items); if (items.isEmpty()) return; switch (act){ case Menu::Alternates: { SearchFrame *sf = ArenaWidgetFactory().create<SearchFrame>(); for (const auto &i : items) sf->searchAlternates(i->data(COLUMN_DOWNLOADQUEUE_TTH).toString()); break; } case Menu::Magnet: { QString magnet = ""; for (const auto &i : items) magnet += WulforUtil::getInstance()->makeMagnet( i->data(COLUMN_DOWNLOADQUEUE_NAME).toString(), i->data(COLUMN_DOWNLOADQUEUE_ESIZE).toLongLong(), i->data(COLUMN_DOWNLOADQUEUE_TTH).toString()) + "\n"; if (!magnet.isEmpty()) qApp->clipboard()->setText(magnet, QClipboard::Clipboard); break; } case Menu::MagnetWeb: { QString magnet = ""; for (const auto &i : items){ magnet += "[magnet=\"" + WulforUtil::getInstance()->makeMagnet( i->data(COLUMN_DOWNLOADQUEUE_NAME).toString(), i->data(COLUMN_DOWNLOADQUEUE_ESIZE).toLongLong(), i->data(COLUMN_DOWNLOADQUEUE_TTH).toString()) + "\"]"+i->data(COLUMN_DOWNLOADQUEUE_NAME).toString()+"[/magnet]\n"; } if (!magnet.isEmpty()) qApp->clipboard()->setText(magnet, QClipboard::Clipboard); break; } case Menu::MagnetInfo: { QString magnet = ""; for (const auto &i : items){ magnet = WulforUtil::getInstance()->makeMagnet( i->data(COLUMN_DOWNLOADQUEUE_NAME).toString(), i->data(COLUMN_DOWNLOADQUEUE_ESIZE).toLongLong(), i->data(COLUMN_DOWNLOADQUEUE_TTH).toString()) + "\n"; if (!magnet.isEmpty()){ Magnet m(this); m.setLink(magnet); m.exec(); } } break; } case Menu::RenameMove: { for (const auto &i : items){ QString target = i->data(COLUMN_DOWNLOADQUEUE_PATH).toString() + i->data(COLUMN_DOWNLOADQUEUE_NAME).toString(); QString new_target = QFileDialog::getSaveFileName(this, tr("Choose filename"), target, tr("All files (*.*)")); if (!new_target.isEmpty() && new_target != target){ new_target = QDir::toNativeSeparators(new_target); try { QM->move(target.toStdString(), new_target.toStdString()); } catch (const Exception &){} } } break; } case Menu::SetPriority: { for (const auto &i : items){ QString target = i->data(COLUMN_DOWNLOADQUEUE_PATH).toString() + i->data(COLUMN_DOWNLOADQUEUE_NAME).toString(); try { QM->setPriority(target.toStdString(), static_cast<QueueItem::Priority>(arg.toInt())); } catch (const Exception&) {} } break; } case Menu::Browse: { rmap = arg.toMap(); QString cid = getCID(rmap); if (d->sources.contains(target) && !cid.isEmpty()){ UserPtr user = ClientManager::getInstance()->findUser(CID(cid.toStdString())); if (user){ try { QM->addList(HintedUser(user, ""), QueueItem::FLAG_CLIENT_VIEW, ""); } catch (const Exception&){} } } break; } case Menu::SendPM: { rmap = arg.toMap(); auto it = rmap.constBegin(); dcpp::CID cid(_tq(getCID(rmap))); QString nick = ((++it).key()); QList<QObject*> list = HubManager::getInstance()->getHubs(); for (const auto &obj : list){ HubFrame *fr = qobject_cast<HubFrame*>(obj); if (!fr) continue; if (fr->hasCID(cid, nick)){ fr->createPMWindow(cid); break; } } break; } case Menu::RemoveSource: { rmap = arg.toMap(); QString cid = getCID(rmap); if (d->sources.contains(target) && !cid.isEmpty()){ UserPtr user = ClientManager::getInstance()->findUser(CID(cid.toStdString())); if (user){ try { QM->removeSource(target.toStdString(), user, QueueItem::Source::FLAG_REMOVED); } catch (const Exception&){} } } break; } case Menu::RemoveUser: { rmap = arg.toMap(); QString cid = getCID(rmap); if (d->sources.contains(target) && !cid.isEmpty()){ UserPtr user = ClientManager::getInstance()->findUser(CID(cid.toStdString())); if (user){ try { QM->removeSource(user, QueueItem::Source::FLAG_REMOVED); } catch (const Exception&){} } } break; } case Menu::Remove: { for (const auto &i : items){ QString target = i->data(COLUMN_DOWNLOADQUEUE_PATH).toString() + i->data(COLUMN_DOWNLOADQUEUE_NAME).toString(); try { QM->remove(target.toStdString()); } catch (const Exception &){} } break; } default: break; } }
Test::Result run_one_test(const std::string& algo, const VarMap& vars) override { Test::Result result("OCB wide block long test"); const std::vector<uint8_t> expected = vars.get_req_bin("Output"); std::unique_ptr<Botan::BlockCipher> cipher; size_t bs = 0; if(algo == "SHACAL2") { #if defined(BOTAN_HAS_SHACAL2) cipher = Botan::BlockCipher::create_or_throw("SHACAL2"); bs = 32; #else return {result}; #endif } else { if(algo == "Toy128") bs = 16; else if(algo == "Toy192") bs = 24; else if(algo == "Toy256") bs = 32; else if(algo == "Toy512") bs = 64; else throw Test_Error("Unknown cipher for OCB wide block long test"); cipher.reset(new OCB_Wide_Test_Block_Cipher(bs)); } Botan::OCB_Encryption enc(cipher.release(), std::min<size_t>(bs, 32)); /* Y, string of length min(B, 256) bits Y is defined as follows. K = (0xA0 || 0xA1 || 0xA2 || ...)[1..B] C = <empty string> for i = 0 to 127 do S = (0x50 || 0x51 || 0x52 || ...)[1..8i] N = num2str(3i+1,16) C = C || OCB-ENCRYPT(K,N,S,S) N = num2str(3i+2,16) C = C || OCB-ENCRYPT(K,N,<empty string>,S) N = num2str(3i+3,16) C = C || OCB-ENCRYPT(K,N,S,<empty string>) end for N = num2str(385,16) Y = OCB-ENCRYPT(K,N,C,<empty string>) */ std::vector<uint8_t> key(bs); for(size_t i = 0; i != bs; ++i) key[i] = 0xA0 + i; enc.set_key(key); const std::vector<uint8_t> empty; std::vector<uint8_t> N(2); std::vector<uint8_t> C; for(size_t i = 0; i != 128; ++i) { std::vector<uint8_t> S(i); for(size_t j = 0; j != S.size(); ++j) S[j] = 0x50 + j; Botan::store_be(static_cast<uint16_t>(3 * i + 1), &N[0]); ocb_encrypt(result, C, enc, N, S, S); Botan::store_be(static_cast<uint16_t>(3 * i + 2), &N[0]); ocb_encrypt(result, C, enc, N, S, empty); Botan::store_be(static_cast<uint16_t>(3 * i + 3), &N[0]); ocb_encrypt(result, C, enc, N, empty, S); } Botan::store_be(static_cast<uint16_t>(385), &N[0]); std::vector<uint8_t> final_result; ocb_encrypt(result, final_result, enc, N, empty, C); result.test_eq("correct value", final_result, expected); return result; }