I have a C++ problem here which I simply cannot understand.
I have 2 slightly different functions. Both of them should do the very same thing. But only one works properly.
Method 1: input of the method is 'const string samplerName = "test"'
void setUniformSampler(Gluint program, const string samplerName, GLuint sampler) {
GLint uniformLocation = glGetUniformLocation(program, samplerName.c_str()); // returns -1
if(uniformLocation >= 0) {
glUniform1i(uniformLocation, sampler);
} else {
throw exception(...);
}
}
Method 2:
void setUniformSampler(Gluint program, GLuint sampler) {
GLint uniformLocation = glGetUniformLocation(program, "test"); // returns 0
if(uniformLocation >= 0) {
glUniform1i(uniformLocation, sampler);
} else {
throw exception(...);
}
}
As you can see, glGetUniformLocation returns 2 different values. The correct return value would be "0", not "-1". So I wonder, what exactly is the difference between the two calls?
quote: "c_str() generates a null-terminated sequence of characters (c-string) with the same content as the string object and returns it as a pointer to an array of characters". And that is precisely what the method glGetUniformLocation(...) needs as its second parameter. So, why does only Method 2 above succeed? Is it a compiler problem?
I'm working with MS Visual Studio 2008 on Win7.
I've been searching for this bug for almost 2 days now. I really want to clarify this. It drove me crazy...
Thanks
Walter
EDIT:
This doesn't work either.
void setUniformSampler(Gluint program, const string samplerName, GLuint sampler) {
const GLchar* name = samplerName.c_str();
GLint uniformLocation = glGetUniformLocation(program, name); // still returns -1
if(uniformLocation >= 0) {
glUniform1i(uniformLocation, sampler);
} else {
throw exception(...);
}
}
Your parameter is const, and you can't call a non-const function on a const object. Maybe that's the problem? The function needs a pointer to a null-terminated string. Make sure that's what you're giving it.
check the implementation and the type of the parameter in glGetUniformLocation(parameter), "test" is a const literal whose life and location never change in your executable's life, while c_str() is dynamically calculated from a string object, it dies when the string object dies.
In other words, you need to check in side of glGetUniformLocation()to find the reason, which I guess is related to some CRT string functions.
You might be victim to a mixup of wide character vs slim (i.e. 8-bit) character strings. If both your shader source and the uniform name are defined as static strings, then they will agree on the string representation. string::c_str might change this, as c_str will always return a string of char, i.e. it is not wchar aware.
Technically it should make difference, since a bug free shader compiler use a unambigous internal representation. But there may be a bug, that the difference between wide and slim characters are interpreted as different identifiers.
What happens if you pass the shader source, too through string::c_str? Also check the debugger hexedit view on the string variable. If it looks like this:
00000000 74 65 73 74 0a |test.|
You got a 8-bit character string. If it looks like this:
00000000 74 00 65 00 73 00 74 00 0a 00 |t.e.s.t...|
then you got a wide string. And then compare this with the variable in which the shader is supplied.
Related
I'm trying to get the length of a character array in a second function. I've looked at a few questions on here (1 2) but they don't answer my particular question (although I'm sure something does, I just can't find it). My code is below, but I get the error "invalid conversion from 'char' to 'const char*'". I don't know how to convert my array to what is needed.
#include <cstring>
#include <iostream>
int ValidInput(char, char);
int main() {
char user_input; // user input character
char character_array[26];
int valid_guess;
valid_guess = ValidGuess(user_input, character_array);
// another function to do stuff with valid_guess output
return 0;
}
int ValidGuess (char user_guess, char previous_guesses) {
for (int index = 0; index < strlen(previous_guesses); index++) {
if (user_guess == previous_guesses[index]) {
return 0; // invalid guess
}
}
return 1; // valid guess, reaches this if for loop is complete
}
Based on what I've done so far, I feel like I'm going to have a problem with previous_guesses[index] as well.
char user_input;
defines a single character
char character_array[26];
defines an array of 26 characters.
valid_guess = ValidGuess(user_input, character_array);
calls the function
int ValidGuess (char user_guess, char previous_guesses)
where char user_guess accepts a single character, lining up correctly with the user_input argument, and char previous_guesses accepts a single character, not the 26 characters of character_array. previous_guesses needs a different type to accommodate character_array. This be the cause of the reported error.
Where this gets tricky is character_array will decay to a pointer, so
int ValidGuess (char user_guess, char previous_guesses)
could be changed to
int ValidGuess (char user_guess, char * previous_guesses)
or
int ValidGuess (char user_guess, char previous_guesses[])
both ultimately mean the same thing.
Now for where things get REALLY tricky. When an array decays to a pointer it loses how big it is. The asker has gotten around this problem, kudos, with strlen which computes the length, but this needs a bit of extra help. strlen zips through an array, counting until it finds a null terminator, and there are no signs of character_array being null terminated. This is bad. Without knowing where to stop strlen will probably keep going1. A quick solution to this is go back up to the definition of character_array and change it to
char character_array[26] = {};
to force all of the slots in the array to 0, which just happens to be the null character.
That gets the program back on its feet, but it could be better. Every call to strlen may recount (compilers are smart and could compute once per loop and store the value if it can prove the contents won't change) the characters in the string, but this is still at least one scan through every entry in character_array to see if it's null when what you really want to do is scan for user_input. Basically the program looks at every item in the array twice.
Instead, look for both the null terminator and user_input in the same loop.
int index = 0;
while (previous_guesses[index] != '\0' ) {
if (user_guess == previous_guesses[index]) {
return 0; // prefer returning false here. The intent is clearer
}
index++;
}
You can also wow your friends by using pointers and eliminating the need for the index variable.
while (*previous_guesses != '\0' ) {
if (user_guess == *previous_guesses) {
return false;
}
previous_guesses++;
}
The compiler knows and uses this trick too, so use the one that's easier for you to understand.
For 26 entries it probably doesn't matter, but if you really want to get fancy, or have a lot more than 26 possibilities, use a std::set or a std::unordered_set. They allow only one of an item and have much faster look-up than scanning a list one by one, so long as the list is large enough to get over the added complexity of a set and take advantage of its smarter logic. ValidGuess is replaced with something like
if (used.find(user_input) != used.end())
Side note: Don't forget to make the user read a value into user_input before the program uses it. I've also left out how to store the previous inputs because the question does as well.
1 I say probably because the Standard doesn't say what to do. This is called Undefined Behaviour. C++ is littered with the stuff. Undefined Behaviour can do anything -- work, not work, visibly not work, look like it works until it doesn't, melt your computer, anything -- but what it usually does is the easiest and fastest thing. In this case that's just keep going until the program crashes or finds a null.
When people hook a function in general they modify the first few instructions of the function they want to hook with branch instructions to where they want to do some stuff then branch back to original function and restore it, the problem with that is that literally nothing is safe. Any value you are trying to hide can easily be found (these values can be found many other ways than just function hooking, but that's all i'm focusing on in this question)
Let's say you go through the effort of implementing a hash algorithm like MD5 into your C++ application (I haven't, this is just an example for the question), just for the sake of this example assume you have a MD5 function like this
void GENERATEMD5(const char *plain, char *out);
and you would call it like
char hashResult[33] = { 0 };//32 + 1 because of null terminator
GENERATEMD5(passwordInputBuffer, hashResult);
memset(passwordInputBuffer, 0, 32);//set password buf back to null
Anyone could easily hook this GERERATEMD5() function and simply print out the parameters as they are passed to the function. Example
void md5FuncHook(const char *plain, char *out)
{
md5Hook(plain, out);
console::print("Plain: %s - Hash: %s", plain, out);
}
I was thinking about it and there was only one way I could come up with detecting if a function is hooked (assuming they have hooked the function via modifying the function's first few instructions). And that would be to check the first few bytes of the function then confirm that they are what they are supposed to be.
Example, if we know the first few bytes of the function GERERATEMD5() are
int GERERATEMD5_Function_bytes_0 = 0x12341234;//just random bytes for the example
int GERERATEMD5_Function_bytes_1 = 0x12341234;//just random bytes for the example
int GERERATEMD5_Function_bytes_2 = 0x12341234;//just random bytes for the example
int GERERATEMD5_Function_bytes_3 = 0x12341234;//just random bytes for the example
Then we could do something like this
void checkIfGENERATEMD5HasBeenHooked()
{
int GERERATEMD5_Function_bytes_0 = 0x12341234;//just random bytes for the example
int GERERATEMD5_Function_bytes_1 = 0x12341234;//just random bytes for the example
int GERERATEMD5_Function_bytes_2 = 0x12341234;//just random bytes for the example
int GERERATEMD5_Function_bytes_3 = 0x12341234;//just random bytes for the example
int readGENERATEMD5FunctionBytes0, readGENERATEMD5FunctionBytes1, readGENERATEMD5FunctionBytes2, readGENERATEMD5FunctionBytes3;
memcpy(&readGENERATEMD5FunctionBytes0, (char *)(&GENERATEMD5 + 0x00), 0x04);
memcpy(&readGENERATEMD5FunctionBytes1, (char *)(&GENERATEMD5 + 0x04), 0x04);
memcpy(&readGENERATEMD5FunctionBytes2, (char *)(&GENERATEMD5 + 0x08), 0x04);
memcpy(&readGENERATEMD5FunctionBytes3, (char *)(&GENERATEMD5 + 0x0C), 0x04);
if(GERERATEMD5_Function_bytes_0 == readGENERATEMD5FunctionBytes0 && GENERATEMD5_Function_bytes_1 == readGENERATEMD5FunctionBytes1 && GENERATEMD5_Function_bytes_2 == readGENERATEMD5FunctionBytes2 && GENERATEMD5_Function_bytes_3 == readGENERATEMD5FunctionBytes3)
{
//our GENERATEMD5() function is clean
}
else
{
//hook detected or some other form of function modification detected
}
}
But with everything I have tried this just never seems to work. The issue I'm assuming is coming from where I read the bytes of the function itself, like the calls to memcpy aren't actually reading the bytes located at &GENERATEMD5 + OFFSET. Am I just doing something wrong? Or is there a better/different way of doing what I'm trying to accomplish? (btw, yes I know there are many other hooking methods attackers may use when hooking your functions other than what I've described above and just in general many other ways to get a hold of your sensitive information from your executable, but this question has nothing to do with any of that so please just focus on the question rather than just saying something along the lines of "doing this is pointless" or "there are easy ways to bypass this", etc...)
I have done this. The problem is the loader will modify the code during relocation so you cannot rely on the operand fields being the same value every time. In my case I used a disassembly library and did a hash on only the opcode bytes. I used BASTARD to do disassembly at runtime but that project is long dead. I think there are better options now.
In principle you could probably write the target function in such a way that relocation fixups wouldn't happen, but that's going to be more trouble than it is worth.
The problem is probably something simple, but I couldn't get it to work after hours of research and editing, so here I post my issue.
I am trying to make a function which receives either a single digit integer or a two digit integer and returns it as a string after converting it to a two integer format (e.g. 7 to 07).
char *to_two_digits(int num) {
char num_str[4];
sprintf(num_str, "%d", num);
int length = sizeof(*num_str) / sizeof(char);
static char *return_string;
if (length == 1) {
sprintf_s(return_string, "0%d", num);
return return_string;
}
else if (length == 2) {
*return_string = *num_str;
return return_string;
}
else {
printf("Error! Number cannot be represented as a two-digit.");
exit(1);
}
}
The function fails when the sprintf_s() function is run, with an error that says:
--------------------------- Microsoft Visual C++ Runtime Library-----------
Debug Assertion Failed!
File: minkernel\crts\ucrt\src\appcrt\stdio\output.cpp
Line: 261
Expression: format != nullptr
What is the problem, and how can I fix it? Thank you in advance.
You are passing a null pointer to the sprintf_s function. The pointer that you declare in this line
static char *return_string;
was never initialized to point to anything. Since it is declared static, it is pre-initialized to zero (rather than just having an indeterminate value).
This is what the message is telling you. There is an assert in the sprintf_s code that checks that you have not passed a null pointer, and that is what is firing.
You are supposed to pass in a pointer to a buffer that the function can write into. But since you are using C++, you're really just supposed to use a std::string for this, which you could then return from the function without needing a static variable.
It's exactly what it says — you're passing a null pointer to sprintf_s.
It's that return_string, which you did not initialise to point to anything, let alone a buffer of sufficient size for the actual result. Rather than being of indeterminate value, it is assuredly a null pointer by virtue of being static, but this assurance doesn't help you.
It's actually not a good idea to use static for memory management like this, because your function is 100% non-re-entrant. Usually you'd have your users pass in a buffer of sufficient size for the result, and let that calling scope handle the buffer's lifetime.
I have the following method in C++ which checks the name at the map
map<string, bool> namesMap;
bool IsValidName(const char* name) {
string currentName(name, 16);
if (MapContains(namesMap, currentName))
return namesMap[currentName];
else
namesMap[currentName] = false;
return false;
}
template<class T, class K>
bool MapContains(const std::map<T, K>& targetMap, const T key) {
return targetMap.find(key) != targetMap.end();
}
Calling IsValidName() sometimes causes to capture the thread into an infinite loop. I've got a memory dump which shows that the thread is stuck in MapContains() method and further at xtree which is internally used by std::map.
All the names at the application are 6-8 characters long. So there is a bug at the line:
string currentName(name, 16);
Which causes all the checked names to have length: 16 instead of the correct one. As a result currentName has correct data in the first 6-8 chars and garbage at the rest ones. So the map is filled with 16-characters long strings with undefined data inside each of them.
Could this garbage cause the infinite loop while searching the map?
Or any other ideas what can cause it?
Update:
As I've described above I know the problem with line:
string currentName(name, 16);
Just want to know how it causes map to have undefined behaviour
Your program has undefined behavior.
The line string currentName(name, 16); attempts to build of string of 16 characters from a const char* pointing to 6-8 characters only.
Solution:
Provide at least 16 characters, or simply call string currentName(name);
I am working on Visual studio C++.
I have these codes:
CString str;
BYTE byBuffer[10000] = { 0 };
str ="Invalid Command. Spaces are not allowed too!!";
strcpy_s(reinterpret_cast<LPSTR>(byBuffer), 10000, T2CA(str ));
The problem is byBuffer = "Invalid Command. Spaces are not allowed too!!"; but after the following line, the string changes.
LPBYTE lp=byBuffer ; Although it works fine for small strings like OK, GOOD JOB. etc..
i am debugging the whole code by setting the breakpoints. moreover this function has been called to another function in which ( LPBYTE lpBuffer) recieved this value.
Plz help
The code you're showing us looks OK, so I'm going out on a limb and making a guess.
I'm guessing that you're trying to return this buffer from a function:
LPBYTE lp = byBuffer;
return lp;
If that's the case, then the local variable byBuffer is getting destroyed at the end of the function and the pointer no longer points to valid memory. You're lucky if you can see anything recognizable in the output at all.