#Compile time buffer overflow preventer

19 messages · Page 1 of 1 (latest)

hollow moat
#

Does anybody have any code or any place where you can read/learn about how to write compile time code that checks a buffer or just memory type in general(for this example only a char buffer) and converts it into a type that has overflow checking like a vector?

tired tartanBOT
#

When your question is answered use !solved to mark the question as resolved.

Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.

gloomy wren
#

Sure, I suppose you could use a template with type traits to convert a buffer of some type into a vector of that type. Not sure that is what you are looking for however.

hollow moat
#

Im just looking for how to do it with as little code as possible

#

Like I understand the premise and that it is possible but I cant find good code online to show how to do it

hollow moat
#

@gloomy wren

gloomy wren
#

This is a simple template. Certainly not a complete solution but give it a buffer of some type and it will give you back a vector of that same type.

template <typename T, std::size_t N>
auto convertToSafeType(T (&buffer)[N]) {
    return std::vector<T>(buffer, buffer + N);
}

There are still unsafe ways to access vectors however. [], multi-threading, invalidation of iterators, to name a few. If you use .at(index) you get bounds checking and it will throw a std::out_of_range if so. You also get things like size, capacity, and empty done safely. I suppose you could create some sort of "safe access" template class, but you could also just learn what is safe and what is not and code accordingly. Still not sure of your goal here...

hollow moat
#

How is it that it returns buffer and buffer+N?

#

@gloomy wren

#

Also can you really iterate the same way with a vector as a array

#

Dont think have different ways of iteration?

#

Also what would be nice to add in this function which is more what im interessted in is how you can restrict a buffer or tell if a buffer or container of any type is suseptable to memory errors

#

Because if im not mistaking you can declare a buffer usin std::array

#

Does array have any ways to prevent memory overflow like vectors do?

gloomy wren
# hollow moat How is it that it returns buffer and buffer+N?

Actually, it returns a vector with the data copied from buffer.

#include <iostream>
#include <vector>
#include <string>

template <typename T, std::size_t N>
auto convertToSafeType(T (&buffer)[N]) {
    return std::vector<T>(buffer, buffer + N);
}

int main()
{
    char buffer[] = "Hello world!";

    auto safeBuffer = convertToSafeType(buffer);
    for (char c : safeBuffer) {
        std::cout << c;
    }
    std::cout << std::endl;
}

I presume you are talking about "invalidation of iterators". This occurs anytime anything changes the internal structure of the vector potentially invalidating pointers, references or iterators such as adding or removing elements, resizing, assignment or swap which can replace the vector contents with another vector.

Again, std::array and std::vector are not bullet-proof. There are unsafe ways to access them which can lead to undefined behaviour. Focus rather on writing safe code would be my advice.

#

By way of example... If I add this line to the end of the code above:

    // Unsafe access
    safeBuffer[100] = 'x';

I will be writing past the end of safeBuffer and stomping on the heap. I can compile with -fsanitize=address and at run time will get further information about what is happening;

$ g++ -g -fsanitize=address foo.cpp
$ ./a.out
Hello world!
=================================================================
==51913==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000074 at pc 0x559e6c99885f bp 0x7ffe7c9020b0 sp 0x7ffe7c9020a0
WRITE of size 1 at 0x602000000074 thread T0
    #0 0x559e6c99885e in main foo.cpp:21
    #1 0x7fee9f4b3d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #2 0x7fee9f4b3e3f in __libc_start_main_impl ../csu/libc-start.c:392
    #3 0x559e6c998444 in _start (a.out+0x2444)

0x602000000074 is located 87 bytes to the right of 13-byte region [0x602000000010,0x60200000001d)

There is a lot more spew, but you get the idea.

#

If instead, I use this form:

safeBuffer.at(100) = 'x';

I will get the following error thrown:

$ ./a.out
Hello world!
terminate called after throwing an instance of 'std::out_of_range'
  what():  vector::_M_range_check: __n (which is 100) >= this->size() (which is 13)
Aborted (core dumped)

At least in this case I can use a try/catch block to know that this error is about to happen or be summarily terminated rather than silently smashing the heap.

hollow moat
#

Yes thank you

#

!solved