void coverQuantisationCornerCases() { // origin at lower end of the time range FixedFrameQuantiser case1 (1, Time::MIN); CHECK (secs(0) == case1.gridAlign(Time::MIN )); CHECK (secs(0) == case1.gridAlign(Time::MIN +TimeValue(1) )); CHECK (secs(1) == case1.gridAlign(Time::MIN +secs(1) )); CHECK (Time::MAX -secs(1) > case1.gridAlign( secs(-1) )); CHECK (Time::MAX -secs(1) <= case1.gridAlign( secs (0) )); CHECK (Time::MAX > case1.gridAlign( secs (0) )); CHECK (Time::MAX == case1.gridAlign( secs(+1) )); CHECK (Time::MAX == case1.gridAlign( secs(+2) )); // origin at upper end of the time range FixedFrameQuantiser case2 (1, Time::MAX); CHECK (secs( 0) == case2.gridAlign(Time::MAX )); CHECK (secs(-1) == case2.gridAlign(Time::MAX -TimeValue(1) )); // note: next lower frame CHECK (secs(-1) == case2.gridAlign(Time::MAX -secs(1) )); // i.e. the same as a whole frame down CHECK (Time::MIN +secs(1) < case2.gridAlign( secs(+2) )); CHECK (Time::MIN +secs(1) >= case2.gridAlign( secs(+1) )); CHECK (Time::MIN < case2.gridAlign( secs(+1) )); CHECK (Time::MIN == case2.gridAlign( secs( 0) )); // note: because of downward truncating, CHECK (Time::MIN == case2.gridAlign( secs(-1) )); // resulting values will already exceed CHECK (Time::MIN == case2.gridAlign( secs(-2) )); // allowed range and thus will be clipped // maximum frame size is half the time range Duration hugeFrame(Time::MAX); FixedFrameQuantiser case3 (hugeFrame); CHECK (Time::MIN == case3.gridAlign(Time::MIN )); CHECK (Time::MIN == case3.gridAlign(Time::MIN +TimeValue(1) )); CHECK (Time::MIN == case3.gridAlign( secs(-1) )); CHECK (TimeValue(0) == case3.gridAlign( secs( 0) )); CHECK (TimeValue(0) == case3.gridAlign( secs(+1) )); CHECK (TimeValue(0) == case3.gridAlign(Time::MAX -TimeValue(1) )); CHECK (Time::MAX == case3.gridAlign(Time::MAX )); // now displacing this grid by +1sec.... FixedFrameQuantiser case4 (hugeFrame, secs(1)); CHECK (Time::MIN == case4.gridAlign(Time::MIN )); CHECK (Time::MIN == case4.gridAlign(Time::MIN +TimeValue(1) )); // clipped... CHECK (Time::MIN == case4.gridAlign(Time::MIN +secs(1) )); // but now exact (unclipped) CHECK (Time::MIN == case4.gridAlign( secs(-1) )); CHECK (Time::MIN == case4.gridAlign( secs( 0) )); CHECK (TimeValue(0) == case4.gridAlign( secs(+1) )); //.....now exactly the frame number zero CHECK (TimeValue(0) == case4.gridAlign(Time::MAX -TimeValue(1) )); CHECK (TimeValue(0) == case4.gridAlign(Time::MAX )); //.......still truncated down to frame #0 // larger frames aren't possible Duration not_really_larger(secs(10000) + hugeFrame); CHECK (hugeFrame == not_really_larger); // frame sizes below the time micro grid get trapped long subAtomic = 2*GAVL_TIME_SCALE; // too small for this universe... VERIFY_ERROR (BOTTOM_VALUE, FixedFrameQuantiser quark(subAtomic) ); VERIFY_ERROR (BOTTOM_VALUE, FixedFrameQuantiser quark(Duration (FSecs (1,subAtomic))) ); }
/** @test OpaqueHolder with additional storage for subclass. * When a subclass requires more storage than the base class or * Interface, we need to create a custom OpaqueHolder, specifying the * actually necessary storage. Such a custom OpaqueHolder behaves exactly * like the standard variant, but there is protection against accidentally * using a standard variant to hold an instance of the larger subclass. * * @test Moreover, if the concrete class has a custom operator bool(), it * will be invoked automatically from OpaqueHolder's operator bool() * */ void checkSpecialSubclass () { typedef OpaqueHolder<Base, sizeof(Special)> SpecialOpaque; cout << showSizeof<Base>() << endl; cout << showSizeof<Special>() << endl; cout << showSizeof<Opaque>() << endl; cout << showSizeof<SpecialOpaque>() << endl; CHECK (sizeof(Special) > sizeof(Base)); CHECK (sizeof(SpecialOpaque) > sizeof(Opaque)); CHECK (sizeof(SpecialOpaque) <= sizeof(Special) + sizeof(void*) + _ALIGN_); Special s1 (6); Special s2 (3); CHECK (!s1); // even value CHECK (s2); // odd value CHECK (7 == s1.getIt()); // indeed subclass of DD<7> CHECK (7 == s2.getIt()); SpecialOpaque ospe0; SpecialOpaque ospe1 (s1); SpecialOpaque ospe2 (s2); CHECK (!ospe0); // note: bool test (isValid) CHECK (!ospe1); // also forwarded to contained object (myVal_==6 is even) CHECK ( ospe2); CHECK ( isnil(ospe0)); // while isnil just checks the empty state CHECK (!isnil(ospe1)); CHECK (!isnil(ospe2)); CHECK (7 == ospe1->getIt()); CHECK (6 == ospe1.get<Special>().myVal_); CHECK (3 == ospe2.get<Special>().myVal_); ospe1 = DD<5>(); // but can be reassigned like any normal Opaque CHECK (ospe1); CHECK (5 == ospe1->getIt()); VERIFY_ERROR (WRONG_TYPE, ospe1.get<Special>() ); Opaque normal = DD<5>(); CHECK (normal); CHECK (5 == normal->getIt()); #if false ////////////////////////////////////////////////////////TODO: restore throwing ASSERT // Assertion protects against SEGV VERIFY_ERROR (ASSERTION, normal = s1 ); #endif//////////////////////////////////////////////////////////// }
void checkStateCapturingMechanism () { function<void(short,int)> undo_func = undo; function< int(short)> cap_func = capture; MemHolder mementoHolder (undo_func,cap_func); CHECK (sizeof(MemHolder) <= sizeof(int) // storage for the memento + 2 * sizeof(function<void()>) // storage for the 2 undecorated functors + ALIGNMENT); function<OpSIG> bound_undo_func = mementoHolder.tieUndoFunc(); function<OpSIG> bound_cap_func = mementoHolder.tieCaptureFunc(); VERIFY_ERROR (MISSING_MEMENTO, bound_undo_func(123) ); VERIFY_ERROR (MISSING_MEMENTO, mementoHolder.getState() ); short rr (rand() %100); testVal = 0; bound_cap_func(rr); // invoke state capturing CHECK (rr == mementoHolder.getState()); testVal = 10; // meanwhile "somehow" mutate the state bound_undo_func(0); // invoking the undo() feeds back the memento CHECK (testVal == 10-rr); // this cycle can be repeated with different state values rr = (rand() %100); testVal = rr; bound_cap_func(5); // capture new state CHECK (5+rr == mementoHolder.getState()); testVal = -20; bound_undo_func(3*rr); CHECK (testVal == -20 + 3*rr - (5+rr)); }
/** @test cover the basic situations of object handling, * especially copy operations and re-assignments */ void checkHandling (TestList& objs) { Opaque oo; CHECK (!oo); CHECK (isnil(oo)); oo = objs[1]; CHECK (oo); CHECK (!isnil(oo)); typedef DD<3> D3; typedef DD<5> D5; D3 d3 (oo.get<D3>() ); CHECK (3 == oo->getIt()); // re-access through Base interface CHECK (!isSameObject (d3, *oo)); VERIFY_ERROR (WRONG_TYPE, oo.get<D5>() ); // direct assignment of target into Buffer oo = D5(); CHECK (oo); CHECK (5 == oo->getIt()); VERIFY_ERROR (WRONG_TYPE, oo.get<D3>() ); // can get a direct reference to contained object D5 &rd5 (oo.get<D5>()); CHECK (isSameObject (rd5, *oo)); CHECK (!isnil(oo)); oo = objs[3]; // copy construction also works on non-empty object CHECK (7 == oo->getIt()); // WARNING: direct ref has been messed up through the backdoor! CHECK (7 == rd5.getIt()); CHECK (isSameObject (rd5, *oo)); uint cnt_before = _create_count; oo.clear(); CHECK (!oo); oo = D5(); // direct assignment also works on empty object CHECK (oo); CHECK (5 == oo->getIt()); CHECK (_create_count == 2 + cnt_before); // one within buff and one for the anonymous temporary D5() // verify that self-assignment is properly detected... cnt_before = _create_count; oo = oo; CHECK (oo); CHECK (_create_count == cnt_before); oo = oo.get<D5>(); CHECK (_create_count == cnt_before); oo = *oo; CHECK (_create_count == cnt_before); CHECK (oo); oo.clear(); CHECK (!oo); CHECK (isnil(oo)); VERIFY_ERROR (BOTTOM_VALUE, oo.get<D5>() ); #if false ///////////////////////////////////////////////////////////////////////////////////////////////TICKET #537 : restore throwing ASSERT VERIFY_ERROR (ASSERTION, oo->getIt() ); #endif ///////////////////////////////////////////////////////////////////////////////////////////////TICKET #537 : restore throwing ASSERT // can't access empty holder... Opaque o1 (oo); CHECK (!o1); Opaque o2 (d3); CHECK (!isSameObject (d3, *o2)); CHECK (3 == o2->getIt()); CHECK (sizeof(Opaque) <= sizeof(Base) + sizeof(void*) + _ALIGN_); }
int jwt_verify_sha_pem(jwt_t *jwt, const char *head, const char *sig_b64) { unsigned char *sig = NULL; EVP_MD_CTX *mdctx = NULL; ECDSA_SIG *ec_sig = NULL; BIGNUM *ec_sig_r = NULL; BIGNUM *ec_sig_s = NULL; EVP_PKEY *pkey = NULL; const EVP_MD *alg; int type; int pkey_type; BIO *bufkey = NULL; int ret = 0; int slen; switch (jwt->alg) { /* RSA */ case JWT_ALG_RS256: alg = EVP_sha256(); type = EVP_PKEY_RSA; break; case JWT_ALG_RS384: alg = EVP_sha384(); type = EVP_PKEY_RSA; break; case JWT_ALG_RS512: alg = EVP_sha512(); type = EVP_PKEY_RSA; break; /* ECC */ case JWT_ALG_ES256: alg = EVP_sha256(); type = EVP_PKEY_EC; break; case JWT_ALG_ES384: alg = EVP_sha384(); type = EVP_PKEY_EC; break; case JWT_ALG_ES512: alg = EVP_sha512(); type = EVP_PKEY_EC; break; default: return EINVAL; } sig = jwt_b64_decode(sig_b64, &slen); if (sig == NULL) VERIFY_ERROR(EINVAL); bufkey = BIO_new_mem_buf(jwt->key, jwt->key_len); if (bufkey == NULL) VERIFY_ERROR(ENOMEM); /* This uses OpenSSL's default passphrase callback if needed. The * library caller can override this in many ways, all of which are * outside of the scope of LibJWT and this is documented in jwt.h. */ pkey = PEM_read_bio_PUBKEY(bufkey, NULL, NULL, NULL); if (pkey == NULL) VERIFY_ERROR(EINVAL); pkey_type = EVP_PKEY_id(pkey); if (pkey_type != type) VERIFY_ERROR(EINVAL); /* Convert EC sigs back to ASN1. */ if (pkey_type == EVP_PKEY_EC) { unsigned int degree, bn_len; unsigned char *p; EC_KEY *ec_key; ec_sig = ECDSA_SIG_new(); if (ec_sig == NULL) VERIFY_ERROR(ENOMEM); /* Get the actual ec_key */ ec_key = EVP_PKEY_get1_EC_KEY(pkey); if (ec_key == NULL) VERIFY_ERROR(ENOMEM); degree = EC_GROUP_get_degree(EC_KEY_get0_group(ec_key)); EC_KEY_free(ec_key); bn_len = (degree + 7) / 8; if ((bn_len * 2) != slen) VERIFY_ERROR(EINVAL); ec_sig_r = BN_bin2bn(sig, bn_len, NULL); ec_sig_s = BN_bin2bn(sig + bn_len, bn_len, NULL); if (ec_sig_r == NULL || ec_sig_s == NULL) VERIFY_ERROR(EINVAL); ECDSA_SIG_set0(ec_sig, ec_sig_r, ec_sig_s); free(sig); slen = i2d_ECDSA_SIG(ec_sig, NULL); sig = malloc(slen); if (sig == NULL) VERIFY_ERROR(ENOMEM); p = sig; slen = i2d_ECDSA_SIG(ec_sig, &p); if (slen == 0) VERIFY_ERROR(EINVAL); } mdctx = EVP_MD_CTX_create(); if (mdctx == NULL) VERIFY_ERROR(ENOMEM); /* Initialize the DigestVerify operation using alg */ if (EVP_DigestVerifyInit(mdctx, NULL, alg, NULL, pkey) != 1) VERIFY_ERROR(EINVAL); /* Call update with the message */ if (EVP_DigestVerifyUpdate(mdctx, head, strlen(head)) != 1) VERIFY_ERROR(EINVAL); /* Now check the sig for validity. */ if (EVP_DigestVerifyFinal(mdctx, sig, slen) != 1) VERIFY_ERROR(EINVAL); jwt_verify_sha_pem_done: if (bufkey) BIO_free(bufkey); if (pkey) EVP_PKEY_free(pkey); if (mdctx) EVP_MD_CTX_destroy(mdctx); if (sig) free(sig); if (ec_sig) ECDSA_SIG_free(ec_sig); return ret; }