Hi OpenFHE Team!
Use OpenFHE in computing the following polynomials with the UBSAN tool:
((NOT (0 AND 0)) AND ((0 OR 0)) AND ((1 OR 0) AND (1 OR 1)) OR ((1 AND 1))) OR ((NOT (NOT 1)) AND ((NOT 0)))
These calculation will causes UBSAN to issue these runtime error. which is
/data/homomorphic/openfhe-1.2.3/openfhe-development/src/binfhe/lib/rgsw-acc.cpp:74:21: runtime error: left shift of 67101697 by 54 places cannot be represented in type 'long int'
/data/homomorphic/openfhe-1.2.3/openfhe-development/src/binfhe/lib/rgsw-acc.cpp:84:22: runtime error: left shift of 65529 by 54 places cannot be represented in type 'long int'
/data/homomorphic/openfhe-1.2.3/openfhe-development/src/binfhe/lib/rgsw-acc.cpp:71:21: runtime error: left shift of negative value -6946191
/data/homomorphic/openfhe-1.2.3/openfhe-development/src/binfhe/lib/rgsw-acc.cpp:78:22: runtime error: left shift of negative value -6783
After conducting a thorough investigation, we have identified some reasons.
In our code, it is the following line that triggered these runtime errors.
auto ctOR = cc.EvalBinGate(OR, ct1, ct2);
and why it triggered a left shift runtime error in the SignedDigitDecompose
function?
Please refer to the following call stack.
#0 0x7f1bc3bce265 in lbcrypto::RingGSWAccumulator::SignedDigitDecompose(std::shared_ptr<lbcrypto::RingGSWCryptoParams> const&, std::vector<lbcrypto::PolyImpl<intnat::NativeVectorT<intnat::NativeIntegerT<unsigned long> > >, std::allocator<lbcrypto::PolyImpl<intnat::NativeVectorT<intnat::NativeIntegerT<unsigned long> > > > > const&, std::vector<lbcrypto::PolyImpl<intnat::NativeVectorT<intnat::NativeIntegerT<unsigned long> > >, std::allocator<lbcrypto::PolyImpl<intnat::NativeVectorT<intnat::NativeIntegerT<unsigned long> > > > >&) const /data/homomorphic/openfhe-1.2.3/openfhe-development/src/binfhe/lib/rgsw-acc.cpp:74
#1 0x7f1bc3e0d659 in lbcrypto::RingGSWAccumulatorCGGI::AddToAccCGGI(std::shared_ptr<lbcrypto::RingGSWCryptoParams> const&, std::shared_ptr<lbcrypto::RingGSWEvalKeyImpl const> const&, std::shared_ptr<lbcrypto::RingGSWEvalKeyImpl const> const&, intnat::NativeIntegerT<unsigned long> const&, std::shared_ptr<lbcrypto::RLWECiphertextImpl>&) const /data/homomorphic/openfhe-1.2.3/openfhe-development/src/binfhe/lib/rgsw-acc-cggi.cpp:112
#2 0x7f1bc3e220a1 in lbcrypto::RingGSWAccumulatorCGGI::EvalAcc(std::shared_ptr<lbcrypto::RingGSWCryptoParams> const&, std::shared_ptr<lbcrypto::RingGSWACCKeyImpl const> const&, std::shared_ptr<lbcrypto::RLWECiphertextImpl>&, intnat::NativeVectorT<intnat::NativeIntegerT<unsigned long> > const&) const /data/homomorphic/openfhe-1.2.3/openfhe-development/src/binfhe/lib/rgsw-acc-cggi.cpp:66
#3 0x7f1bc3c546e5 in lbcrypto::BinFHEScheme::BootstrapGateCore(std::shared_ptr<lbcrypto::BinFHECryptoParams> const&, lbcrypto::BINGATE, std::shared_ptr<lbcrypto::RingGSWACCKeyImpl const> const&, std::shared_ptr<lbcrypto::LWECiphertextImpl const> const&) const /data/homomorphic/openfhe-1.2.3/openfhe-development/src/binfhe/lib/binfhe-base-scheme.cpp:538
#4 0x7f1bc3c597e1 in lbcrypto::BinFHEScheme::EvalBinGate(std::shared_ptr<lbcrypto::BinFHECryptoParams> const&, lbcrypto::BINGATE, lbcrypto::RingGSWBTKey const&, std::shared_ptr<lbcrypto::LWECiphertextImpl const> const&, std::shared_ptr<lbcrypto::LWECiphertextImpl const> const&, bool) const /data/homomorphic/openfhe-1.2.3/openfhe-development/src/binfhe/lib/binfhe-base-scheme.cpp:100
#5 0x7f1bc3d19956 in lbcrypto::BinFHEContext::EvalBinGate(lbcrypto::BINGATE, std::shared_ptr<lbcrypto::LWECiphertextImpl const> const&, std::shared_ptr<lbcrypto::LWECiphertextImpl const> const&, bool) const /data/homomorphic/openfhe-1.2.3/openfhe-development/src/binfhe/lib/binfhecontext.cpp:281
#6 0x40932d in analysis(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, lbcrypto::BinFHEContext, std::shared_ptr<lbcrypto::LWEPrivateKeyImpl>) /data/homomorphic/test-openfhe/demo_boolean_symmetric.cpp:89
#7 0x40ca65 in main /data/homomorphic/test-openfhe/demo_boolean_symmetric.cpp:266
#8 0x7f1bbcc32082 in __libc_start_main ../csu/libc-start.c:308
#9 0x4078bd in _start (/data/homomorphic/test-openfhe/new-build/test+0x4078bd)
Due to the excessive depth of function calls in the program, our GDB was unable to trace the specific values of the parameters passed at each level.
UBSAN tool detects two different errors: one being a left shift of a negative value, and the other being a left shift that cannot be represented in type ‘long int’. Therefore, I believe that these two errors are likely to affect the correctness of the OR Boolean function in the SignedDigitDecompose function.
Is these two are bug? I think these two behaviour trigger C++ undefined behaviour which it can be cause some degree of SignedDigitDecompose calculation error. At the same time, you can print out why the SignedDigitDecompose function sometimes performs a left shift on negative numbers or causes an integer overflow during left shifts, to investigate the true reason. By the way the error messages vary depending on the specific polynomial .
Thank you for taking the time to look into this issue. Please let us know if any further details or clarification would be helpful!
Best regards,
wowblk