I have two structure
struct TbtStreamHeader
{
short MsgLen;
short StreamId;
int SeqNo;
TbtStreamHeader()
{
MsgLen = StreamId = 0;
SeqNo = 0;
}
};
struct Multicast_OrderMsg
{
char MsgType; ///'N', 'X', 'M'
long long Timestamp;
double OrderId;
int Token;
char OrderType;
int Price;
int Quantity;
string ToString()
{
std::stringstream ss;
ss<<MsgType<<'|'<<Timestamp<<'|'<<(long long)OrderId<<"|0|"<<Token<<'|'<<OrderType<<'|'<<Price<<'|'<<Quantity;
return ss.str();
}
};
I am reading a file using ifstream, filling that file into the structure object because file is not into the format of structure, then copy the structure into char buffer. Here is the code for better understanding.
TbtStreamHeader hdr;
Multicast_OrderMsg oMsg;
hdr.MsgLen = 38;
hdr.StreamId = streamID;
hdr.SeqNo = 0;
bool firstLine = true;
while(ifs1)
{
if (!getline(ifs1, str1)) break;
istringstream ss(str1);
v1.clear();
while(ss)
{
string s1;
if(!getline( ss, s1, '|' ))
{
break;
}
v1.push_back(s1);
}
if(firstLine)
{
firstLine = false;
seq = atoi(v1[1].c_str());
hdr.SeqNo = seq;
getline(ifs1, str1);
}
else
{
char tempData[38];
int tempBufOffset=0;
hdr.SeqNo++;
oMsg.OrderId = atoll(v1[0].c_str());
oMsg.Token = atoi(v1[1].c_str());
oMsg.OrderType = v1[2][0];
oMsg.Price = atoi(v1[3].c_str());
oMsg.Quantity = atoi(v1[4].c_str());
oMsg.MsgType = 'N';
memcpy(tempData, &hdr, 8);
tempBufOffset += 8;
memcpy(tempData+tempBufOffset, oMsg, 30);
Multicast_OrderMsg* oMsgT = (Multicast_OrderMsg*)tempData+8; //Not able to caste
cout<<oMsgT->ToString()<<endl;
tempBufOffset += 30;
mcastTbt.streams[0].RecoveryPacket(tempData);
}
}
Here cout<< showing me segmentation fault. I am not able to understanding what wrong it is..?
At the location tempData+8 are no Multicast_OrderMsg objects, dereferencing such pointer is undefined behaviour as it violates the strict aliasing rule.
But that on itself does not usually cause seg. faults, the reason is tempData is not big enough to store the aliased Multicast_OrderMsg object. On most implementation the types require to be aligned at least to their size, which causes padding:
struct Multicast_OrderMsg
{
char MsgType; // 1
// Padding 7
long long Timestamp;// 8
double OrderId;// 8
int Token;// 4
char OrderType;// 1
// Padding 3
int Price;// 4
int Quantity;// 4
};
Making the structure 40 bytes long, you only have space for 30. So the printing tries to access memory locations not belonging to you, hence the segfault.
Related
int computeHMACSHA1Hash(const char * unhashedcstr, char * hashedcstr, const char * key, int returncode)
{
string hashed;
size_t unhashlength = strlen(unhashedcstr);
char * nonconstunhashcstr = new char[unhashlength];
strcpy_s(nonconstunhashcstr, unhashlength + 1, unhashedcstr);
unsigned char* pixels = reinterpret_cast<unsigned char*>(nonconstunhashcstr);
returncode = 0;
HMAC_CTX* context = HMAC_CTX_new();
size_t unhashedstrlength = sizeof(unhashedcstr);
if (context != NULL)
{
if (HMAC_Init_ex(context, key, strlen(key), EVP_sha1(), NULL))
{
if (HMAC_Update(context, pixels, unhashedstrlength))
{
unsigned char hash[EVP_MAX_MD_SIZE];
unsigned int lengthOfHash = 0;
if (HMAC_Final(context, hash, &lengthOfHash))
{
std::stringstream ss;
for (unsigned int i = 0; i < lengthOfHash; ++i)
{
ss << std::hex << std::setw(2) << std::setfill('0') << (int)hash[i];
}
hashed = ss.str();
size_t outputSize = hashed.length() + 1; // +1 for null terminator
strcpy_s(hashedcstr, outputSize, hashed.c_str());
returncode = 0;
}
else
{
returncode = 7;
}
}
else
{
returncode = 6;
}
}
else
{
returncode = 5;
}
HMAC_CTX_free(context);
}
else
{
returncode = 4;
}
return returncode;
}
int main()
{
const char * unhashedcstr = "a=services&l=v1&p=open&k=SD58292829&i=20200918125249803&n=2124&t=1600404769&f={\"invoiceCode\": \"11111\",\"invoiceNo\": \"2222\",\"inTaxAmount\": \"\",\"exTaxAmount\": \"\"}";
char * hashedcstr = new char[100];
int returncode = 0;
const char * key = "SD886A11B0EE428F";
int result = computeHMACSHA1Hash(unhashedcstr, hashedcstr, key, returncode);
return 0;
}
I tried the code above to calculating the HMAC SHA1 hash value for a content, but compared the results on https://www.freeformatter.com/hmac-generator.html#before-output
it looks like I didn't do it right. I'm not sure what I have done wrong though. Any help would be appreciated.
It turned out the result was "d916b4c2d277319bbf18076c158f0cbcf6c3bc57", while on the website https://www.freeformatter.com/hmac-generator.html#before-output, the result was "71482b292f2b2a47b3eca6dad5e7350566d60963". Even when I tried using the string "a=services&l=v1&p=open&k=SD58292829&i=20200918125249803&n=2124&t=1600404769&f={"invoiceCode": "11111","invoiceNo": "2222","inTaxAmount": "","exTaxAmount": ""}" which removed the escape characters, the result was "09be98b6129c149e685ed57a1d19651a602cda0d". It didn't match the correct one.
Is there anything wrong with my code?
Your hash is calculated over the bytes a=se, which are the first four bytes of the whole input string. Thus, you get d916b4c2d277319bbf18076c158f0cbcf6c3bc57 instead of the 09be98b6129c149e685ed57a1d19651a602cda0d that would correspond to the whole string.
The reason is this:
size_t unhashedstrlength = sizeof(unhashedcstr);
Here, sizeof(unhashedcstr) is the size of the unhashedcstr pointer itself (which is of type const char*), not the size of the null-terminated C-style string this unhashedcstr pointer is pointing to. You are compiling a 32-bit program, so the size of a pointer is 4 bytes. Thus, unhashedstrlength is 4.
To get the length of the C-style string, you can do this instead:
size_t unhashedstrlength = strlen(unhashedcstr);
But just as a comment, in modern C++, you should avoid using raw pointers (such as const char*, char*, unsigned char*), C functions (like strlen(), strcpy_s()) and manual memory management (new / delete and new[] / delete[]). You should prefer to use std::string and/or std::vector<unsigned char> instead, wherever possible. When you need to pass a buffer's address to an API function, you can use std::string::data(), std::vector::data(), or more generally, std::data().
By the way, you currently leak memory: you dynamically allocate buffers using new[], but you never deallocate those (using delete[]). So that memory is released by the OS only after the program exits. This is called a memory leak.
#include<string>
#include<cstring>
class Solution {
void shift_left(char* c, const short unsigned int bits) {
const unsigned short int size = sizeof(c);
memmove(c, c+bits, size - bits);
memset(c+size-bits, 0, bits);
}
public:
string longestPalindrome(string s) {
char* output = new char[s.length()];
output[0] = s[0];
string res = "";
char* n = output;
auto e = s.begin() + 1;
while(e != s.end()) {
char letter = *e;
char* c = n;
(*++n) = letter;
if((letter != *c) && (c == &output[0] || letter != (*--c)) ) {
++e;
continue;
}
while((++e) != s.end() && c != &output[0]) {
if((letter = *e) != (*--c)) {
const unsigned short int bits = c - output + 1;
shift_left(output, bits);
n -= bits;
break;
}
(*++n) = letter;
}
string temp(output);
res = temp.length() > res.length()? temp : res;
shift_left(output, 1);
--n;
}
return res;
}
};
input string longestPalindrome("babad");
the program works fine and prints out "bab" as the longest palindrome but there's a heap overflow somewhere. Error like this appears:
Read of size 6 at ...memory address... thread T0
"babad" is size 5 and after going over this for an hour. I don't see the point where the iteration ever exceeds 5
There is 3 pointers here that iterate.
e as the element of string s.
n which is the pointer to the next char of output.
and c which is a copy of n and decrements until it reaches the address of &output[0].
maybe it's something with the memmove or memset since I've never used it before.
I'm completely lost
TL;DR : mixture of char* and std::string are not really good idea if you don't understand how exactly it works.
If you want to length of string you cant do this const unsigned short int size = sizeof(c); (sizeof will return size of pointer (which is commonly 4 on 32-bit machine and 8 on 64-bit machine). You must do this instead: const size_t size = strlen(c);
Address sanitizers is right that you (indirectly) are trying to get an memory which not belongs to you.
How does constructor of string from char* works?
Answer: char* is considered as c-style string, which means that it must be null '\0' terminated.
More details: constructor of string from char* calls strlen-like function which looks like about this:
https://en.cppreference.com/w/cpp/string/byte/strlen
int strlen(char *begin){
int k = 0;
while (*begin != '\0'){
++k;
++begin;
}
return k;
}
If c-style char* string does not contain '\0' it cause accessing memory which doesn't belongs to you.
How to fix?
Answer (two options):
not use mixture of char* and std::string
char* output = new char[s.length()]; replace with char* output = new char[s.length() + 1]; memset(output, 0, s.length() + 1);
Also you must delete all memory which you newed. So add delete[] output; before return res;
I'm trying convert vector to char * for send by socket
the type of T is a simple struct
struct CategoryStruct {
int ID;
char name[32];
};
std::vector<CategoryStruct> categories;
Function, where I'm trying to convert -
char * Category::decodeCategoryToCharArray()
{
int structSize = sizeof(CategoryStruct),
currentByte = 0,
i = 0;
if(decoded)
delete [] decoded;
decoded = new char[structSize * categories.size()];
std::vector<CategoryStruct>::iterator start, end;
start = categories.begin();
end = categories.end();
for(; start != end; start++, i++)
{
memcpy(decoded+currentByte, &categories[i], structSize);
currentByte += structSize+1;
}
return decoded;
}
End return will be ""
There's no need for conversion, std::vector<CategoryStruct> already stores the data in a contigous memory area. so your function could be boiled down to
std::vector<CategoryStruct> categories;
char * Category::decodeCategoryToCharArray()
{
return reinterpret_cast<char*>(categories.data());
}
I am trying to implement my own version of strncpy(), i found a source code from this link.
But I encountered a Unhandled exception at 0x00411ad5 in exercise 2.exe: 0xC0000005: Access violation writing location 0x00417800. everytime the code reaches this code while((x++ < n) && (*dest++ = *source++));
Here is the complete code:
char *strncpy(char * destination, const char * source, size_t n){
char *dest;
dest = destination;
size_t x=0;
while((x++ < n) && (*dest++ = *source++)); //this is where unhandled exception occurs
while(x++ < n){
*dest++ = 0;
}
return dest;
}
int main(){
char *sample = "blue";
char * sample2 = "red";
cout << strncpy(sample, sample2, 5);
getch();
return 0;
}
Please tell me why this occurs and how should I fix it? Thanks!
Your destination is "blue" which is a string literal, that is a constant. As such it is located in a read-only part of memory (and pointed at by local sample variable), thus error when writing.
Try this:
int main(){
char sample[] = "blue";
char * sample2 = "red";
cout << strncpy(sample, sample2, 5);
getch();
return 0;
}
which makes sample an array in local, writeable memory.
You cannot write to a string constant (sample); write to a char array instead:
int main(){
char *sample = "blue";
char buffer[5];
cout << strncpy(buffer, sample, sizeof(buffer));
getch();
return 0;
}
First, it was already explained to you that you can't overwrite a string that is defined like that.
Second, you cant use cout << strncpy if that function returns pointer to the end of the copied string.
There are two main problems with your program
The first one is that function strncpy has to return destination instead of dest
char *strncpy(char * destination, const char * source, size_t n){
char *dest;
dest = destination;
size_t x=0;
while((x++ < n) && (*dest++ = *source++)); //this is where unhandled exception occurs
while(x++ < n){
*dest++ = 0;
}
// return dest;
return destination;
}
The second one is that string literals are immutable. Any attempt to modify a string literal results in undefined behaviour.
Thus main function should be rewritten the following way
int main(){
char sample[] = "blue";
char * sample2 = "red";
cout << strncpy(sample, sample2, sizeof( sample ) );
getch();
return 0;
}
Also it is a bad style of programming to use variable with name x as a count. It is better to use for example i.
I would write the function simpler
char * strncpy( char *destination, const char *source, size_t n )
{
char *dest = destination;
while ( n-- && ( *dest++ = *source++ ) );
while ( n-- ) *dest++ = '\0';
return destination;
}
I want to read the memory from a process for 16 MB (FFFFFF) and store it in a array, in a way that when I search inside the array like: array[i], i will be the real memory address.
Lets say I want to search from 000000 to FFFFFF, I want to make that jump sizeof(value), get the address from that address and store it in a var.
then if(var==value) return address.
i have this:
ReadProcessMemory(phandle,(void*)address,buffer,0xFFFFFF,0);
EDIT:
i have this (by BlueWanderer answer):
class offset_buffer{
private:
char *buf;
int offset;
public:
offset_buffer(char *in_buf, int in_offset)
: buf(in_buf), offset(in_offset){
}
char & operator[](int in_index){
return buf[in_index - offset];
}
void setOffset(int off){
offset=off;
}
void ReadMemory(){
LPBYTE point;
DWORD primeiroAddress = 0x000000;
DWORD finalAddress = 0xFFFFFF;
//LPBYTE buffer = new BYTE[finalAddress-primeiroAddress];
HANDLE phandle = OpenProcess(PROCESS_VM_READ,0,TargetPID);
ReadProcessMemory(phandle,(void*)primeiroAddress, buf, sizeof(buf), 0);
CloseHandle(phandle);
}
};
main(){
char *buffer = new char[0xFFFFFFF-0x0000000];
int address = 0x0000000;
offset_buffer b(buffer,address);
std::ostringstream ss;
int i=0;
TListItem *ListIt;
b.ReadMemory();
for(address=0x0000000;address<0xFFFFFFF;address+=sizeof(int)){
if(b[address]==StrToInt(Edit1->Text.c_str())){
ss << std::hex << address;
showValue();
ss.str(std::string());
}
}
what is wrong?? can someone help me? why it doesn't work
You want something like this?
class offset_buffer
{
private:
char *buf;
int offset;
public:
offset_buffer(char *in_buf, int in_offset)
: buf(in_buf), offset(in_offset)
{
}
char & operator[](int in_index)
{
return buf[in_index - offset];
}
};
It will map your real address to the index in the array
offset_buffer b(buffer, address);
if (b[0x0C2F8E3] == 123) return 0x0C2F8E3;