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

Malformed EXI Document Causes Decoding Error #99

Closed
brandonprry opened this issue Dec 9, 2024 · 4 comments
Closed

Malformed EXI Document Causes Decoding Error #99

brandonprry opened this issue Dec 9, 2024 · 4 comments
Labels
bug Something isn't working

Comments

@brandonprry
Copy link

Describe the bug

ISO Version

ISO15118-20

Describe the bug

A malformed EXI document can cause an exception.

To Reproduce

Compile the following harness.

#include <cbv2g/exi_v2gtp.h>
#include <iso15118/message/schedule_exchange.hpp>
#include <iso15118/message/variant.hpp>
#include <iostream>
#include <vector>
#include <cstdlib>
#include <iso15118/io/stream_view.hpp>

uint8_t* readAllStdin(size_t& length) {
    
    std::vector<uint8_t> buffer;
    char temp;

    // Read all input data from stdin
    while (std::cin.get(temp)) {
        buffer.push_back(static_cast<uint8_t>(temp));
    }

    // Allocate memory for the buffer and copy the data
    length = buffer.size();
    uint8_t* data = new uint8_t[length];
    std::copy(buffer.begin(), buffer.end(), data);

    return data;
}

int main()
{

    size_t len;
    uint8_t* data = readAllStdin(len);

    const iso15118::io::StreamInputView stream_view{data, len};
    iso15118::message_20::Variant variant(iso15118::io::v2gtp::PayloadType::Part20Main, stream_view);

}
g++ main.cpp -I ./libiso15118/build/_deps/libcbv2g-src/include/ -I libiso15118/include/ libiso15118/build/src/iso15118/libiso15118.a ./libiso15118//build/_deps/libcbv2g-build/lib/cbv2g/libcbv2g_tp.a libiso15118/build/_deps/libcbv2g-build/lib/cbv2g/libcbv2g_iso20.a libiso15118/build/_deps/libcbv2g-build/lib/cbv2g/libcbv2g_exi_codec.a -fprofile-arcs -ftest-coverage -o test

Pass the malformed EXI document over stdin with valgrind.

bperry@bperry-Precision-T5610:~/tmp$ echo "QIRAAAlpAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAnACcnDk5MDk5OTk5OTk5OTk5OTA5OTkCADAAnQEAFQo=" | base64 --decode | valgrind ./test
==2570672== Memcheck, a memory error detector
==2570672== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==2570672== Using Valgrind-3.22.0 and LibVEX; rerun with -h for copyright info
==2570672== Command: ./test
==2570672== 
terminate called after throwing an instance of 'std::bad_optional_access'
  what():  bad optional access
==2570672== 
==2570672== Process terminating with default action of signal 6 (SIGABRT)
==2570672==    at 0x4CA3B1C: __pthread_kill_implementation (pthread_kill.c:44)
==2570672==    by 0x4CA3B1C: __pthread_kill_internal (pthread_kill.c:78)
==2570672==    by 0x4CA3B1C: pthread_kill@@GLIBC_2.34 (pthread_kill.c:89)
==2570672==    by 0x4C4A26D: raise (raise.c:26)
==2570672==    by 0x4C2D8FE: abort (abort.c:79)
==2570672==    by 0x4915FF4: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.33)
==2570672==    by 0x492B0D9: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.33)
==2570672==    by 0x4915A54: std::terminate() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.33)
==2570672==    by 0x492B390: __cxa_throw (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.33)
==2570672==    by 0x117BD1: __throw_bad_optional_access (optional:111)
==2570672==    by 0x117BD1: value (optional:1005)
==2570672==    by 0x117BD1: void iso15118::message_20::convert<iso20_ServiceSelectionReqType, iso15118::message_20::ServiceSelectionRequest>(iso20_ServiceSelectionReqType const&, iso15118::message_20::ServiceSelectionRequest&) [clone .cold] (service_selection.cpp:20)
==2570672==    by 0x145548: insert_type<iso15118::message_20::ServiceSelectionRequest, iso20_ServiceSelectionReqType> (variant_access.hpp:30)
==2570672==    by 0x145548: void iso15118::message_20::insert_type<iso20_ServiceSelectionReqType>(iso15118::message_20::VariantAccess&, iso20_ServiceSelectionReqType const&) (service_selection.cpp:42)
==2570672==    by 0x123562: iso15118::message_20::handle_main(iso15118::message_20::VariantAccess&) (variant.cpp:58)
==2570672==    by 0x1249AF: iso15118::message_20::Variant::Variant(iso15118::io::v2gtp::PayloadType, iso15118::io::StreamInputView const&) (variant.cpp:123)
==2570672==    by 0x11C8D0: main (main.cpp:34)
==2570672== 
==2570672== HEAP SUMMARY:
==2570672==     in use at exit: 78,084 bytes in 5 blocks
==2570672==   total heap usage: 14 allocs, 9 frees, 78,371 bytes allocated
==2570672== 
==2570672== LEAK SUMMARY:
==2570672==    definitely lost: 0 bytes in 0 blocks
==2570672==    indirectly lost: 0 bytes in 0 blocks
==2570672==      possibly lost: 136 bytes in 1 blocks
==2570672==    still reachable: 77,948 bytes in 4 blocks
==2570672==         suppressed: 0 bytes in 0 blocks
==2570672== Rerun with --leak-check=full to see details of leaked memory
==2570672== 
==2570672== For lists of detected and suppressed errors, rerun with: -s
==2570672== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Aborted
bperry@bperry-Precision-T5610:~/tmp$ 

Anything else?

bperry@bperry-Precision-T5610:~/tmp/libiso15118$ git status
On branch main
Your branch is up to date with 'origin/main'.

nothing to commit, working tree clean
bperry@bperry-Precision-T5610:~/tmp/libiso15118$ git rev-parse HEAD
a50c9af1296f04881a3be5d00fe4e02b1559521b
bperry@bperry-Precision-T5610:~/tmp/libiso15118$ 

To Reproduce

Steps above.

Anything else?

No response

@brandonprry brandonprry added the bug Something isn't working label Dec 9, 2024
@barsnick
Copy link
Contributor

The description is incorrect, as there is no "assertion failure" in cbexigen or its generated code. (This assertion triggers in the wrapping code from libiso15118.)

I think what you are trying to describe is that the cbv2g EXI codec should return an error on decoding this document, but doesn't, right?

How was this document created? What does it represent? How is it malformed? Is it random?

The nature of EXI implies a knowledge of the grammar on both sides, the encoder and the decoder. If you throw something random at the decoder which resembles an EXI stream, and (even coincidentally) adheres to a chain of decoder grammars, no error will be detected. If the streams contains a bit sequence which is not allowed according to the schema-informed decoder grammar, the decoder will return an error.

If you can describe why the given document should be decoded differently, please do so.

It would also be nice if you could create a reproducer based only on libcbv2g code.

@brandonprry
Copy link
Author

This one is not the assertion failure. I opened a second one that resulted in an assertion failure in libiso15118. The other bug I opened (#100) is the assertion failure.

Unfortunately I only reproduced these through libiso15118.

I was only told to re-open this here from the libiso15118 repository. These were crashes were found with fuzzing.

@brandonprry
Copy link
Author

This was originally opened here.

EVerest/libiso15118#52

@barsnick
Copy link
Contributor

barsnick commented Jan 2, 2025

The EXI stream is not strictly illegal. Your encoding is choosing a particle which isn't supposed to be there.

The user of the codec currently needs to catch this. This was an omission in libiso15118, which will be fixed.

An alternative is the solution outlined in issue #101, where the codec would return an error if such a non-valid particle appears. It can be discussed whether the codec needs to do this, but I don't consider this issue valid right now.

By the way, it seems you are throwing random stuff at the decoder to find crashes? We should not even have tolerated your header bytes (analyzed in #102, fixed in #103).

@barsnick barsnick closed this as completed Jan 2, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants