Code Monkey home page Code Monkey logo

Comments (18)

oncecrossover avatar oncecrossover commented on August 28, 2024 1

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.

brevilo avatar brevilo commented on August 28, 2024

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.

brevilo avatar brevilo commented on August 28, 2024

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.

brevilo avatar brevilo commented on August 28, 2024

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.

brevilo avatar brevilo commented on August 28, 2024

I chose to merge the fix without your (additional) test such that main gets fixed...

from jolm.

oncecrossover avatar oncecrossover commented on August 28, 2024

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.

oncecrossover avatar oncecrossover commented on August 28, 2024
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.

brevilo avatar brevilo commented on August 28, 2024

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.

brevilo avatar brevilo commented on August 28, 2024

I got it, this error happens with SpringJUnit4ClassRunner/SpringBootTest. It works fine with TestInstance, and never happens with TestInstance.
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.

oncecrossover avatar oncecrossover commented on August 28, 2024

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.

oncecrossover avatar oncecrossover commented on August 28, 2024
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.

brevilo avatar brevilo commented on August 28, 2024

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.

brevilo avatar brevilo commented on August 28, 2024

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.

brevilo avatar brevilo commented on August 28, 2024

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.

brevilo avatar brevilo commented on August 28, 2024

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.

oncecrossover avatar oncecrossover commented on August 28, 2024

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.

oncecrossover avatar oncecrossover commented on August 28, 2024

I think this bug has been fixed, you can release a new version.

from jolm.

brevilo avatar brevilo commented on August 28, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.