Comments (18)
Hey @brevilo , I have tested with branch fix-4-2, It looks great. then we will deploy to live environment to validate it.
Please wait...
from jolm.
This is a strange one. While I can reproduce it occasionally in Eclipse, I never can reproduce it via Maven. Where do you encounter it?
from jolm.
For reference: the JVM segfault is triggered while deserializing the identity keys JSON string into the IdentityKeys
POJO in Account.identityKeys()
using FasterXML's jackson-databind.
No idea why. It also happens with a fixed simple JSON literal. Seems to be related to class loading (presumably of the POJO) and I see references to java/security/ProtectionDomain
. Hm...
from jolm.
Sooo.... this one turned out to be a tricky little bugger! Should be fixed now in branch fix-4
.
@oncecrossover, please give it a try and report back. I'll merge #6 if it fixes the issue for you as well.
Note: there's a reason why I list "Memory management audit" as part of the TODOs in the README 😏
from jolm.
I chose to merge the fix without your (additional) test such that main
gets fixed...
from jolm.
Sorry! I forgot this ticket.
I have tested it many times but still exists. Remarkably, it only seems to happen in unit tests.
from jolm.
git diff:
-@RunWith(SpringJUnit4ClassRunner.class)
-@SpringBootTest(classes = TestApplication.class)
+@TestInstance(TestInstance.Lifecycle.PER_CLASS)
I got it, this error happens with SpringJUnit4ClassRunner/SpringBootTest
. It works fine with TestInstance
, and never happens with TestInstance
.
But why?
May be the same problem in #7.
from jolm.
I can't reproduce the issue. Please provide a test case that isolates the issue and allows me to reproduce it.
Also, which version of jOlm and which JVM are you using now? Is the error's stacktrace still the same?
from jolm.
I got it, this error happens with
SpringJUnit4ClassRunner/SpringBootTest
. It works fine withTestInstance
, and never happens withTestInstance
.
But why?
Here's an idea: TestInstance
causes all tests methods to share their state by using the PER_CLASS
lifecycle (instead of the PER_METHOD
default). Since you don't provide your actual test code I have to assume that your Spring-based unit tests might invalidate the state and in turn the memory blocks backing the Account
and/or Session
instances between the individual test methods. Unless you can prove this to be wrong (by a test case reproducing the issue), I think the error you see is an artifact of the way you run your unit tests.
from jolm.
TestOlmSession.java
package net.metachain.server.utils;
import io.github.brevilo.jolm.Account;
import io.github.brevilo.jolm.Session;
import io.github.brevilo.jolm.model.Message;
import net.metachain.server.TestApplication;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.Map;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = TestApplication.class)
public class TestOlmSession {
private static final Logger LOGGER = LoggerFactory.getLogger(TestOlmSession.class);
/**
* Basic test:
* - alice creates an account
* - bob creates an account
* - alice creates an outbound session with bob (bobIdentityKey & bobOneTimeKey)
* - alice encrypts a message with its session
* - bob creates an inbound session based on alice's encrypted message
* - bob decrypts the encrypted message with its session
*/
@Test
public void testAliceToBob() {
String plainMessage = "Hello Bob, this is message from Alice.";
LOGGER.info("plain message: {}", plainMessage);
String decryptedMessage = "";
String bobIdentityKey = null;
String bobOneTimeKey = null;
Account aliceAccount = null;
Account bobAccount = null;
Session aliceSession = null;
Session bobSession = null;
try {
// ALICE & BOB ACCOUNTS CREATION
aliceAccount = new Account();
Assert.assertNotNull(aliceAccount);
bobAccount = new Account();
Assert.assertNotNull(bobAccount);
// generate identityKey
bobIdentityKey = bobAccount.identityKeys().getCurve25519();
/**
* generate oneTimeKey
*/
bobAccount.generateOneTimeKeys(5);
Map<String, String> bobOneTimeKeys = bobAccount.oneTimeKeys().getCurve25519();
for (String key : bobOneTimeKeys.keySet()) {
bobOneTimeKey = bobOneTimeKeys.get(key);
LOGGER.info("OneTimeKeys: {} = {}", key, bobOneTimeKey);
}
LOGGER.info("identityKey = {}, oneTimeKey = {}", bobIdentityKey, bobOneTimeKey);
// create OutboundSession to Bob
aliceSession = Session.createOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey);
Assert.assertNotNull(aliceSession);
Message encryptedMessage = aliceSession.encrypt(plainMessage);
LOGGER.info("encrypted message: {}", JSONUtils.toJSONString(encryptedMessage));
LOGGER.info("encrypted message type: {}", encryptedMessage.type());
bobSession = Session.createInboundSession(bobAccount, encryptedMessage.getCipherText());
Assert.assertNotNull(bobSession);
decryptedMessage = bobSession.decrypt(encryptedMessage);
LOGGER.info("decrypted message: {}", decryptedMessage);
} catch (Exception e) {
LOGGER.error("Olm session test error: ", e);
} finally {
aliceAccount.clear();
bobAccount.clear();
aliceSession.clear();
bobSession.clear();
}
Assert.assertEquals(plainMessage, decryptedMessage);
}
}
TestApplication.java
@SpringBootApplication(scanBasePackages = {"net.metachain.server"},
exclude = {DataSourceAutoConfiguration.class})
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(TestApplication.class);
}
}
This is my full code, I used spring-boot framework, you can use it to reproduce the error. run three or five times you will reproduce it.
from jolm.
package net.metachain.server.utils;
import io.github.brevilo.jolm.Account;
import io.github.brevilo.jolm.Session;
import io.github.brevilo.jolm.model.Message;
import org.junit.Assert;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
public class TestOlmSession {
private static final Logger LOGGER = LoggerFactory.getLogger(TestOlmSession.class);
/**
* Basic test:
* - alice creates an account
* - bob creates an account
* - alice creates an outbound session with bob (bobIdentityKey & bobOneTimeKey)
* - alice encrypts a message with its session
* - bob creates an inbound session based on alice's encrypted message
* - bob decrypts the encrypted message with its session
*/
@Test
public void testAliceToBob() {
String plainMessage = "Hello Bob, this is message from Alice.";
LOGGER.info("plain message: {}", plainMessage);
String decryptedMessage = "";
String bobIdentityKey = null;
String bobOneTimeKey = null;
Account aliceAccount = null;
Account bobAccount = null;
Session aliceSession = null;
Session bobSession = null;
try {
// ALICE & BOB ACCOUNTS CREATION
aliceAccount = new Account();
Assert.assertNotNull(aliceAccount);
bobAccount = new Account();
Assert.assertNotNull(bobAccount);
// generate identityKey
bobIdentityKey = bobAccount.identityKeys().getCurve25519();
/**
* generate oneTimeKey
*/
bobAccount.generateOneTimeKeys(5);
Map<String, String> bobOneTimeKeys = bobAccount.oneTimeKeys().getCurve25519();
for (String key : bobOneTimeKeys.keySet()) {
bobOneTimeKey = bobOneTimeKeys.get(key);
LOGGER.info("OneTimeKeys: {} = {}", key, bobOneTimeKey);
}
LOGGER.info("identityKey = {}, oneTimeKey = {}", bobIdentityKey, bobOneTimeKey);
// create OutboundSession to Bob
aliceSession = Session.createOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey);
Assert.assertNotNull(aliceSession);
Message encryptedMessage = aliceSession.encrypt(plainMessage);
LOGGER.info("encrypted message: {}", JSONUtils.toJSONString(encryptedMessage));
LOGGER.info("encrypted message type: {}", encryptedMessage.type());
bobSession = Session.createInboundSession(bobAccount, encryptedMessage.getCipherText());
Assert.assertNotNull(bobSession);
decryptedMessage = bobSession.decrypt(encryptedMessage);
LOGGER.info("decrypted message: {}", decryptedMessage);
} catch (Exception e) {
LOGGER.error("Olm session test error: ", e);
} finally {
aliceAccount.clear();
bobAccount.clear();
aliceSession.clear();
bobSession.clear();
}
Assert.assertEquals(plainMessage, decryptedMessage);
}
}
This is my new test code, not used spring-boot test framework, it never reproduce the error.
from jolm.
Thanks, I'm going to look into the issue but with a somewhat lower priority since, so far, it concerns only a specific unit test framework you use and there's a workaround for it.
Stay tuned...
from jolm.
So, here we go again.
Please check out branch fix-4-2
and see if it fixes this issue (as well as #7) for you and let me know.
from jolm.
That's good news! Please try and make sure to throw all tests you have at it (incl. those that triggered #7). Would be great if we could wrap this up once and for all 😏
from jolm.
Hey @oncecrossover, any updates on your tests? I'd like to merge the fixes as soon as possible so that everyone can benefit from them. There are also a few other changes/improvements in the pipeline waiting for the next release.
Thanks
from jolm.
Sorry @brevilo, I had planned to test it for a week.
But now, let me tell you good news, our service is running start from UTC 2021-11-21 19:04:36
, it works fine! Great job! 👍
from jolm.
I think this bug has been fixed, you can release a new version.
from jolm.
Ok, thanks. I'll merge the fix and close this one. A new release should be published over the weekend (at the latest).
from jolm.
Related Issues (9)
- io.github.brevilo.jolm.Utils$OlmException: BAD_MESSAGE_FORMAT HOT 7
- Support JDK 1.8 in maven repository HOT 6
- io.github.brevilo.jolm.Utils$OlmException: BAD_MESSAGE_MAC HOT 4
- Fatal error: Problematic frame: # C [jna8893831892584865540.tmp+0x9220] HOT 1
- java.lang.IllegalArgumentException: Allocation size must be greater than zero HOT 2
- Add olm test libs for Windows/Mac/Linux HOT 4
- Sponsoring jOlm HOT 4
- Add CI build workflows for macOS and Windows
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from jolm.