Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CBOR loses Map entries with specific long Map key values (32-bit boundary) #269

Closed
Quantum64 opened this issue Mar 30, 2021 · 8 comments
Closed
Labels
Milestone

Comments

@Quantum64
Copy link

Quantum64 commented Mar 30, 2021

The issue only appears to occur with large keys of opposite sign. See the below reproducer.

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.cbor.CBORFactory;

import java.util.HashMap;
import java.util.Map;

public class CBORLongMapReproducer {
    private static final ObjectMapper json = new ObjectMapper();
    private static final ObjectMapper cbor = new ObjectMapper(new CBORFactory());

    public static void main(String[] args) throws Exception {
        Map<Long, String> map = new HashMap<>();
        map.put(4294967296L, "hello");
        map.put(-4294967296L, "world");
        TestData data = new TestData();
        data.setMap(map);

        Map<Long, String> resultCbor = cbor.readValue(cbor.writeValueAsBytes(data), TestData.class).getMap();
        Map<Long, String> resultJson = json.readValue(json.writeValueAsBytes(data), TestData.class).getMap();

        System.out.println("JSON size: " + resultJson.size());
        System.out.println("CBOR size: " + resultCbor.size());
    }

    public static class TestData {
        private Map<Long, String> map;

        public void setMap(Map<Long, String> map) {
            this.map = map;
        }

        public Map<Long, String> getMap() {
            return map;
        }
    }
}

This program produces the following output:

JSON size: 2
CBOR size: 1
@cowtowncoder
Copy link
Member

Quick question @Quantum64: which version? (2.12.2 ideally)

@Quantum64
Copy link
Author

Quantum64 commented Mar 31, 2021

It's 2.12.2. The issue only occurs with specific positive/negative key pairs that seem to be relatively rare. I have an algorithm that can generate an arbitrary number of them if you need more. This issue caused a very difficult to diagnose bug in our codebase as you might imagine. :)

@cowtowncoder
Copy link
Member

@Quantum64 yes, that sounds like an absolutely nightmare bug from user perspective. Thank you for reporting this: I'll have a look. Without looking I am guessing it'd have to do with auto-detection of smallest unit to use, and asymmetry b/w positive/negative 2-complement numbers (one more negative value than positive). And just speculating, right at boundary of 32-bit unsigned number.

@cowtowncoder
Copy link
Member

Oh. And it's Longs as keys... that's interesting. CBOR being different from JSON, Smile etc in allowing native non-String keys (which is a royal PITA to support but I digress :) ).

@cowtowncoder
Copy link
Member

I can reproduce this, and looks like this might actually be on generator side (... which is unfortunate).
But definitely an edge condition like you say, near by values do not get truncated to ints (leading to first corrupted value, and then mismatch).

@cowtowncoder cowtowncoder changed the title CBOR loses map entries with opposite sign long keys CBOR loses Map entries with specific long Map key values (32-bit boundary) Mar 31, 2021
@cowtowncoder cowtowncoder modified the milestones: 2.10.0, 2.12.3 Mar 31, 2021
@cowtowncoder
Copy link
Member

Ok it was two-part problem, actually. Partially there was incomplete fix wrt #30 for long-key case; partly missing handling on generator side.

Fixed for upcoming 2.12.3, but backported in 2.11 branch too: just not sure if and how to release; so far was hoping to avoid releasing anything more from 2.11, but this bug might qualify. That should probably be a micro-patch but that gets bit trickier with multi-project repos.

But first it'd be great if you could validate/verify the fix. I did push

  • 2.11.5-SNAPSHOT
  • 2.12.3-SNAPSHOT

of jackson-dataformat-cbor. Or you could build from 2.11 or 2.12 branch locally.

It'd be great to make sure this covers all cases: I did find couple of other ones beyond 2 values listed and think handling is fixed but better safe than sorry.

@Quantum64
Copy link
Author

I can confirm that we are no longer observing any issues on 2.12.3-SNAPSHOT. Thanks for the quick fix!

@cowtowncoder
Copy link
Member

@Quantum64 thank you! I hope to release 2.12.3 within next 2 weeks, depending on whether other issues are found in near future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants