C++ memcpy not copying as expected - c++

BYTE* uMemory;
std::string data = "00 00 00 2D 01 00 B0 F9 1E 00"
data.erase(remove_if(data.begin(), data.end(), isspace), data.end());
int address = 0;
for (int i = 0; i < data.length(); i += 2)
{
std::string data_1 = data.substr(i, 2);
int num2 = std::stoi(data_1, 0, 16);
memcpy(&uMemory + address, &num2, 2);
address++;
}
I'm trying to copy this into memory (2E 01 00 00 00 2D 01 00 B0 F9 1E 00) for uMemory but I don't understand the logic of it.
No matter the amount of bytes I want it to copy it always ends up like this in memory:
00 00 00 00 00 00 00 00 00 01 00 00 2D 00 00 00 01 00 00 00 00 00 00 00 B0 00 00 00 F9 00 00 00 1E 00 00 00

Your immediate problem here is that uMemory is a pointer, and in the line
memcpy(&uMemory + address, &num2, 2);
you are forming a pointer to a pointer. &uMemory has type BYTE**, so when you do pointer arithmetic you're moving over one pointer-width each time, which is apparently 4 bytes on your platform judging by your output.
You're also clobbering a random section of memory of when you write here, likely the memory holding the data object itself (since that's what's declared immediately after the pointer.)

This was my solution. I would love some alternatives for better coding practices if possible.
std::atomic<BYTE> uMemory[256];
int address = 0;
std::vector<BYTE> array;
for (int i = 0; i < data.length(); i += 2)
{
std::string data_1 = data.substr(i, 2);
DWORD num2 = std::stoi(data_1, 0, 16);
array.push_back(num2);
}
std::copy(std::begin(array), std::end(array), std::begin(uMemory));
The only thing I'm not understanding is that I have to have std::atomic in order for the memory to not become random. Is there a different way of doing this?

Related

Find the K-Beauty of a Number Unexpected Runtime Error

I was recently doing the first question in the Leetcode Biweekly Competition 78, and I received an unexpected runtime error which I couldn't understand, especially since I had written similar code before which worked fine. I'm quite new to programming and these competitions, please tell me what this Runtime Error means and how I could change my code to fix it.
class Solution {
public:
int divisorSubstrings(int num, int k) {
string b=to_string(num);
string a="";
int x;
int ans=0;
for(int i=0;i<=b.size()-k;++i){
for(int j=i;i<i+k;++j){
a+=b[j];
}
x=stoi(a);
if(num%x==0){
++ans;
}
}
return ans;
}
};
And the error:
=================================================================
==33==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffca3ed0900 at pc 0x000000343d81 bp 0x7ffca3ed0890 sp 0x7ffca3ed0888
READ of size 1 at 0x7ffca3ed0900 thread T0
#2 0x7fe89b85d0b2 (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
Address 0x7ffca3ed0900 is located in stack of thread T0 at offset 96 in frame
This frame has 4 object(s):
[32, 40) '__endptr.i'
[64, 96) 'b' <== Memory access at offset 96 overflows this variable
[128, 160) 'a'
[192, 193) 'ref.tmp'
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
(longjmp and C++ exceptions *are* supported)
Shadow bytes around the buggy address:
0x1000147d20d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000147d20e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000147d20f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000147d2100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000147d2110: 00 00 00 00 f1 f1 f1 f1 f8 f2 f2 f2 00 00 00 00
=>0x1000147d2120:[f2]f2 f2 f2 00 00 00 00 f2 f2 f2 f2 f8 f3 f3 f3
0x1000147d2130: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000147d2140: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
0x1000147d2150: 01 f2 04 f2 00 00 00 00 00 00 00 00 00 00 00 00
0x1000147d2160: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000147d2170: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==33==ABORTING
If you need the question, it is at https://leetcode.com/contest/biweekly-contest-78/problems/find-the-k-beauty-of-a-number/
Thanks
Your problem is this line of code:
for(int j=i;i<i+k;++j){
You have two habits you should break. First, you don't use white space. That makes the error in this line much harder to read. Second, you use very short variable names. That ALSO makes the error in this line harder to read.
That for-loop loops forever. The problem is the center clause:
i < i + k
Notice how obvious it is when I add spaces? This problem will get worse as you get older and your eyes get older. The code begins to resemble a wall of unreadable text. Old farts like me won't be able to read your code.
So please, add a little white space. I would have written that line like this:
for (int j = i; j < i + k; ++j) {
Yes, it takes more horizontal space. Space is cheap. Bugs are expensive.
Note that I still think this code is going to go out of range of b's size, so you might still have issues.
Here's the accepted solution modified from your snippet. Review the changes made.
class Solution {
public:
int divisorSubstrings(int num, int k) {
string b = to_string(num);
int ans = 0;
for(int i = 0; i <= b.size() - k; i++) { // the error causing crash
string a = ""; // keep declation close to it's usage, compiler will optimize declaration
for(int j = i; j < i + k; j++) a += b[j];
int x = stoi(a);
if (!x) continue; // you might not want to devide by 0
if( num % x == 0 ) ans++;
}
return ans;
}
};

Getting e_lfanew from a dll, yielding E8 and not F8?

I'm reading a DLL file to a buffer (pSrcData), from here I wanted print the e_lfanew
bool readDll(const char* dllfile)
{
BYTE* pSrcData;
std::ifstream File(dllfile, std::ios::binary | std::ios::ate);
auto FileSize = File.tellg();
pSrcData = new BYTE[static_cast<UINT_PTR>(FileSize)];
File.seekg(0, std::ios::beg);
File.read(reinterpret_cast<char*>(pSrcData), FileSize);
File.close();
std::cout << std::hex << reinterpret_cast<IMAGE_DOS_HEADER*>(pSrcData)->e_lfanew;
pOldNtHeader = reinterpret_cast<IMAGE_NT_HEADERS*>(pSrcData + reinterpret_cast<IMAGE_DOS_HEADER*>(pSrcData)->e_lfanew);
return true;
}
Output: E8
Opening the dll in HxD i get this (address 0000000 - 00000030):
4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00
B8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 F8 00 00 00
Meaning e_lfanew should be F8. However, I get E8 when running the code above. Can anyone see what I'm doing wrong?
Addition:
Getting e_magic works as std::cout << std::hex << reinterpret_cast<IMAGE_DOS_HEADER*>(pSrcData)->e_magic yields 5a4d, using little endian translated to 4D 5A
Sorry, I found setting the configuration in Visual Studio 2019 to x86 Release sets e_lfanew to F9 and x86 Debug sets e_lfanew to E8. I was comparing different debug/release versions.

Sending user defined struct through Apache Qpid

I try to send a user defined struct which contains substructs over AMQP from one node to another. I am using the Apache Qpid library at the moment.
(I'm currently still testing my code on the PC before i rebuild it for my other devices)
my current method consist of a conversion from the struct to a bytestring and sending that over AMQP to deconverse it on the other side.
I do the following
//user defined struct
enum Quality
{
/// <summary>Value is reliable.</summary>
QUALITY_GOOD,
/// <summary>Value not reliable.</summary>
/// <remarks>
/// A variable may be declared unreliable if a sensor is not calibrated or
/// if the last query failed but older samples are still usable.
/// </remarks>
QUALITY_UNCERTAIN,
/// <summary>Value is invalid.</summary>
/// <remarks>
/// A variable may be declared bad if the measured value is out of range or
/// if a timeout occured.
/// </remarks>
QUALITY_BAD
};
struct Payload
{
/// <summary>Identifier that uniquely points to a single instance.</summary>
DdsInterface::Id id = DdsInterface::Id();
/// <summary>Human readable short name.</summary>
std::string name = "default";
/// <summary>Actual value.</summary>
long long value;
/// <summary>Quality of the Value.</summary>
Quality quality = QUALITY_GOOD;
/// <summary>Detailed quality of the variable.</summary>
QualityDetail qualityDetail = 0;
/// <summary>Unit of measure.</summary>
PhysicalQuantity quantity = 0;
Payload();
Payload(const DdsInterface::Id id, const std::string topic, const uint64_t counter);
};
//sender function
void QpidAMQP::AMQPPublish(const Payload& payload, bool durability, bool sync)
{
// Publish to MQTT broker
qpid::messaging::Message message;
message.setDurable(durability);
char b[sizeof (payload)];
memcpy(b, &payload, sizeof(payload));
//create stream of bytes to send over the line
message.setContent(b);
//message.setContent("testIfSend");
std::string temp = message.getContent();
print_bytes(temp.c_str(), sizeof (temp));// used to check the byte data
this->sender.send(message);
this->session.sync(sync);
}
//receiver functions
void *check_for_incoming_messages(QpidAMQP* amqp_instance) //called via pthread
{
qpid::messaging::Message message;
std::cout << "check for incoming messages" << std::endl;
while(amqp_instance->getReceiver()->fetch(message, qpid::messaging::Duration::FOREVER))
{
amqp_instance->on_message(&message);
}
return nullptr;
}
void QpidAMQP::on_message(qpid::messaging::Message *message)
{
/// make sure message topic and payload are copied!!!
if (this->handler)
{
std::string temp = message->getContent();
print_bytes(temp.c_str(), sizeof (temp)); // used to check the byte data
Payload payload; //Re-make the struct
memcpy(&payload, message->getContent().c_str(), message->getContentSize());
handler->ReceivedIntegerValue(payload.id.variableId, payload.value);
}
}
I did check the byte data and they where vastly different.
sender:
[ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 63 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 60 32 bf 74 ff 7f 00 00 05 00 00 00 00 00 00 00 74 6f 70 69 63 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ]
receiver:
>[ 74 65 73 74 49 66 53 65 6e 64 00 00 00 7f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 a0 ed ff 43 57 7f 00 00 07 00 00 00 00 00 00 00 64 65 66 61 75 6c 74 00 6d 05 77 4b 57 7f 00 00 ff ff ff ff ff ff ff ff 00 00 00 00 00 00 00 00 ]
I used the following code to print this out
void print_bytes(const void *object, size_t size)
{
// This is for C++; in C just drop the static_cast<>() and assign.
const unsigned char * const bytes = static_cast<const unsigned char *>(object);
size_t i;
printf("[ ");
for(i = 0; i < size; i++)
{
printf("%02x ", bytes[i]);
}
printf("]\n");
}
When i send only a string instead of the payload it receives on the other end. But for some reason a user defined struct doesn't work.
i want to avoid remapping everything against the qpid map because i will lose the depth of my Payload.id.
If someone has any sugestions to overcome this i would appreciatie it.
Thanks in advance,
Nick
I solved the issue.
the problem was that instead of the string instance it copied a pointer instance. By making the std::string name = "default"; into char name[20] = "default"; it copies the real character string.
This is how the publisher and subscriber encode en decode the message now.
void QpidAMQP::AMQPPublish(const Payload& payload, bool durability, bool sync)
{
// Publish to MQTT broker
//create stream of bytes to send over the line
qpid::messaging::Message message;
message.setDurable(durability);
std::string b;
b.resize(sizeof(Payload));
std::memcpy(const_cast<char*>(b.c_str()), &payload, b.size());
message.setContent(b);
std::string temp = message.getContent();
print_bytes(temp.c_str(), temp.size());
this->sender.send(message);
this->session.sync(sync);
}
void QpidAMQP::on_message(qpid::messaging::Message *message)
{
/// make sure message topic and payload are copied!!!
if (this->handler != nullptr)
{
const std::string temp = message->getContent();
print_bytes(temp.c_str(), temp.size());
Payload payload;
std::memcpy(&payload, temp.c_str(), temp.size());//sizeof(message->getContentBytes().c_str()));
handler->ReceivedIntegerValue(payload.id.variableId, payload.value);
}
}

couldn't write specific content into stringstream

I have some sample code reading some binary data from file and then writing the content into stringstream.
#include <sstream>
#include <cstdio>
#include <fstream>
#include <cstdlib>
std::stringstream * raw_data_buffer;
int main()
{
std::ifstream is;
is.open ("1.raw", std::ios::binary );
char * buf = (char *)malloc(40);
is.read(buf, 40);
for (int i = 0; i < 40; i++)
printf("%02X ", buf[i]);
printf("\n");
raw_data_buffer = new std::stringstream("", std::ios_base::app | std::ios_base::out | std::ios_base::in | std::ios_base::binary);
raw_data_buffer -> write(buf, 40);
const char * tmp = raw_data_buffer -> str().c_str();
for (int i = 0; i < 40; i++)
printf("%02X ", tmp[i]);
printf("\n");
delete raw_data_buffer;
return 0;
}
With a specific input file I have, the program doesn't function correctly. You could download the test file here.
So the problem is, I write the file content into raw_data_buffer and immediately read it back, and the content differs. The program's output is:
FFFFFFC0 65 59 01 00 00 00 00 00 00 00 00 00 00 00 00 FFFFFFE0 0A 40 00 00 00 00 00 FFFFFF80 08 40 00 00 00 00 00 70 FFFFFFA6 57 6E FFFFFFFF 7F 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FFFFFFE0 0A 40 00 00 00 00 00 FFFFFF80 08 40 00 00 00 00 00 70 FFFFFFA6 57 6E FFFFFFFF 7F 00 00
The content FFFFFFC0 65 59 01 is overwritten with 0. Why so?
I suspect this a symptom of undefined behavior from using deallocated memory. You're getting a copy of the string from the stringstream but you're only grabbing a raw pointer to the internals that is then immediately deleted. (the link actually warns against this exact case)
const char* tmp = raw_data_buffer->str().c_str();
// ^^^^^ returns a temporary that is destroyed
// at the end of this statement
// ^^^ now a dangling pointer
Any use of tmp would exhibit undefined behavior and could easily cause the problem you're seeing. Keep the result of str() in scope.

Why it reads the file correctly only at second time

I have a file which first 64 bytes are:
0x00: 01 00 00 10 00 00 00 20 00 00 FF 03 00 00 00 10
0x10: 00 00 00 10 00 00 FF 03 00 00 00 10 00 00 FF 03
0x20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
When i'm reading the file (mode read and write) at position 26 for 4 bytes I get 0 and the next time (at position 30) i get correctly 4096.
The code is:
// read LastDirectoryBlockStartByte...
seekg(26);
char * pCUIBuffer = new char[4];
read(pCUIBuffer, 4);
const unsigned int x1 = gcount ();
const unsigned int LastDirectoryBlockStartByte = *(unsigned int *)pCUIBuffer;
// read LastDirectoryBlockNumberItems...
seekg(30);
read(pCUIBuffer, 4);
const unsigned int x2 = gcount ();
const unsigned int LastDirectoryBlockNumberItems = *(unsigned int *)pCUIBuffer;
With gcount() I checked the bytes are read - and this were correctly both times 4.
I have no idea to debug it.
---------- EDIT ----------
When I use the following code (with some dummy before) it reads correctly:
char * pCUIBuffer = new char[4];
seekg(26);
read(pCUIBuffer, 4);
const unsigned int x1 = gcount ();
seekg(26);
read(pCUIBuffer, 4);
const unsigned int x2 = gcount ();
const unsigned int LastDirectoryBlockStartByte = *(unsigned int *)pCUIBuffer;
// read LastDirectoryBlockNumberItems...
seekg(30);
read(pCUIBuffer, 4);
const unsigned int x3 = gcount ();
const unsigned int LastDirectoryBlockNumberItems = *(unsigned int *)pCUIBuffer;
The difficulty is that the code stands at the begining in a methode. And the "false readed value" has obviously nothing to do with the listed code. Maybe theres a trick with flush or sync (but both I tryed...) or somewhat else...
You are saying that pCUIBuffer contains a pointer:
*(unsigned int *)pCUIBuffer;
And then you go get whatever it's pointing at...in RAM. That could be anything.
Now I'm writing an answer, because my attempt to contact TonyK failes (I asked for writing an answer).
The perfect answer to my question was to enable exceptions by calling exceptions (eofbit | failbit | badbit).
Rumo