Can the code of some C++ class accidentally overwrite a private static variable of another class?
I mean a scenario like this: There is some class (I call it victim
) with a private data member and another class (named attacker
) with some method, which, of course, normally does not have access to private members of other classes and does not even hold a reference to an instance of victim
:
extern "C" {
#include <pigpiod_if2.h>
}
class victim {
private:
static bool is_ready;
static bool is_on;
public:
static void init ()
{
is_ready = true;
is_on = true;
}
/* Some other public methods go here. */
}
class attacker {
private:
static int last_read_pin;
public:
static void run ()
{
while (true) {
/* Some sensible code goes here. */
last_read_pin = -1;
time_sleep (0.01); // Using nanosleep () does not change behavior.
}
}
}
This is just a code snippet to illustrate the following question: Is it possible, not just in theory, but also practically, that attacker::run ()
can modify the values of the two private static vars of victim
unintentionally, without addressing any public member of victim
, maybe due to undefined behavior or even a compiler bug? Thank you.
UPDATE: After a hint from another user, I did rebuild the complete app using make clean
and make
. Also, I added the endless loop into my example. The change in is_ready
occurs during the sixth run of the loop. Changing the sleep interval does not change behavior, though.
UPDATE #2: I ran my code through gdb
with a watch on the is_ready
variable, and I got an alert when last_read_pin
was set to –1:
Hardware watchpoint 1: is_ready
Old value = true
New value = false
attacker::Run ()
last_read_pin = -1;
UPDATE #3: Moving last_read_pin
into the Run ()
method itself, thereby making it an internal variable, does not help either.
UPDATE #4: After simply commenting out the line of code, which makes so much trouble, the issue still persisten, apparently being caused by one line above, which reads like this:
keypad::last_levels [h] [k] = 0;
I had to comment out this line, too, to get rid of the problem with is_ready
being changed.
Could the use of pigpiod
cause this issue? I an earlier version, I was using pigpio
directly and did not encounter this problem.
Compiled with gcc 4.9.2.
c++ undefined-behavior private-members
|
show 5 more comments
I mean a scenario like this: There is some class (I call it victim
) with a private data member and another class (named attacker
) with some method, which, of course, normally does not have access to private members of other classes and does not even hold a reference to an instance of victim
:
extern "C" {
#include <pigpiod_if2.h>
}
class victim {
private:
static bool is_ready;
static bool is_on;
public:
static void init ()
{
is_ready = true;
is_on = true;
}
/* Some other public methods go here. */
}
class attacker {
private:
static int last_read_pin;
public:
static void run ()
{
while (true) {
/* Some sensible code goes here. */
last_read_pin = -1;
time_sleep (0.01); // Using nanosleep () does not change behavior.
}
}
}
This is just a code snippet to illustrate the following question: Is it possible, not just in theory, but also practically, that attacker::run ()
can modify the values of the two private static vars of victim
unintentionally, without addressing any public member of victim
, maybe due to undefined behavior or even a compiler bug? Thank you.
UPDATE: After a hint from another user, I did rebuild the complete app using make clean
and make
. Also, I added the endless loop into my example. The change in is_ready
occurs during the sixth run of the loop. Changing the sleep interval does not change behavior, though.
UPDATE #2: I ran my code through gdb
with a watch on the is_ready
variable, and I got an alert when last_read_pin
was set to –1:
Hardware watchpoint 1: is_ready
Old value = true
New value = false
attacker::Run ()
last_read_pin = -1;
UPDATE #3: Moving last_read_pin
into the Run ()
method itself, thereby making it an internal variable, does not help either.
UPDATE #4: After simply commenting out the line of code, which makes so much trouble, the issue still persisten, apparently being caused by one line above, which reads like this:
keypad::last_levels [h] [k] = 0;
I had to comment out this line, too, to get rid of the problem with is_ready
being changed.
Could the use of pigpiod
cause this issue? I an earlier version, I was using pigpio
directly and did not encounter this problem.
Compiled with gcc 4.9.2.
c++ undefined-behavior private-members
6
Yes, anything is possible with undefined behavior.
– melpomene
Nov 16 at 23:11
I am pretty sure you can abuse the language to do this on purpose (aka it's very obvious when you do it), I don't exactly recall how though. Maybe you are reading uninitialized memory (likely), corrupting the object memory (less likely) or encountering just another sort of weirdness in your real usecase - assuming your question is related to a real problem in a larger codebase.
– Asu
Nov 16 at 23:13
5
The private mechanism in C++ isn't a security system, and can be pretty trivially be got around. However, it's unlikely (though not impossible) that you can modify private member variables unintentionally.
– Neil Butterworth
Nov 16 at 23:19
2
Easy to do with a versioning problem. Old non-recompiled code uses a new class that is bigger.
– Hans Passant
Nov 17 at 0:31
3
If code like this leads to behaviour like you describe, you are most likely dealing with either a compiler bug or a hardware bug. Though one cannot exclude UB that occurs elsewhere weirdly interacting with this code. Another pissibility is gdb misidentifying the offending line. It is really hard to tell without seeing the whole picture.
– n.m.
Nov 18 at 16:45
|
show 5 more comments
I mean a scenario like this: There is some class (I call it victim
) with a private data member and another class (named attacker
) with some method, which, of course, normally does not have access to private members of other classes and does not even hold a reference to an instance of victim
:
extern "C" {
#include <pigpiod_if2.h>
}
class victim {
private:
static bool is_ready;
static bool is_on;
public:
static void init ()
{
is_ready = true;
is_on = true;
}
/* Some other public methods go here. */
}
class attacker {
private:
static int last_read_pin;
public:
static void run ()
{
while (true) {
/* Some sensible code goes here. */
last_read_pin = -1;
time_sleep (0.01); // Using nanosleep () does not change behavior.
}
}
}
This is just a code snippet to illustrate the following question: Is it possible, not just in theory, but also practically, that attacker::run ()
can modify the values of the two private static vars of victim
unintentionally, without addressing any public member of victim
, maybe due to undefined behavior or even a compiler bug? Thank you.
UPDATE: After a hint from another user, I did rebuild the complete app using make clean
and make
. Also, I added the endless loop into my example. The change in is_ready
occurs during the sixth run of the loop. Changing the sleep interval does not change behavior, though.
UPDATE #2: I ran my code through gdb
with a watch on the is_ready
variable, and I got an alert when last_read_pin
was set to –1:
Hardware watchpoint 1: is_ready
Old value = true
New value = false
attacker::Run ()
last_read_pin = -1;
UPDATE #3: Moving last_read_pin
into the Run ()
method itself, thereby making it an internal variable, does not help either.
UPDATE #4: After simply commenting out the line of code, which makes so much trouble, the issue still persisten, apparently being caused by one line above, which reads like this:
keypad::last_levels [h] [k] = 0;
I had to comment out this line, too, to get rid of the problem with is_ready
being changed.
Could the use of pigpiod
cause this issue? I an earlier version, I was using pigpio
directly and did not encounter this problem.
Compiled with gcc 4.9.2.
c++ undefined-behavior private-members
I mean a scenario like this: There is some class (I call it victim
) with a private data member and another class (named attacker
) with some method, which, of course, normally does not have access to private members of other classes and does not even hold a reference to an instance of victim
:
extern "C" {
#include <pigpiod_if2.h>
}
class victim {
private:
static bool is_ready;
static bool is_on;
public:
static void init ()
{
is_ready = true;
is_on = true;
}
/* Some other public methods go here. */
}
class attacker {
private:
static int last_read_pin;
public:
static void run ()
{
while (true) {
/* Some sensible code goes here. */
last_read_pin = -1;
time_sleep (0.01); // Using nanosleep () does not change behavior.
}
}
}
This is just a code snippet to illustrate the following question: Is it possible, not just in theory, but also practically, that attacker::run ()
can modify the values of the two private static vars of victim
unintentionally, without addressing any public member of victim
, maybe due to undefined behavior or even a compiler bug? Thank you.
UPDATE: After a hint from another user, I did rebuild the complete app using make clean
and make
. Also, I added the endless loop into my example. The change in is_ready
occurs during the sixth run of the loop. Changing the sleep interval does not change behavior, though.
UPDATE #2: I ran my code through gdb
with a watch on the is_ready
variable, and I got an alert when last_read_pin
was set to –1:
Hardware watchpoint 1: is_ready
Old value = true
New value = false
attacker::Run ()
last_read_pin = -1;
UPDATE #3: Moving last_read_pin
into the Run ()
method itself, thereby making it an internal variable, does not help either.
UPDATE #4: After simply commenting out the line of code, which makes so much trouble, the issue still persisten, apparently being caused by one line above, which reads like this:
keypad::last_levels [h] [k] = 0;
I had to comment out this line, too, to get rid of the problem with is_ready
being changed.
Could the use of pigpiod
cause this issue? I an earlier version, I was using pigpio
directly and did not encounter this problem.
Compiled with gcc 4.9.2.
c++ undefined-behavior private-members
c++ undefined-behavior private-members
edited Nov 18 at 23:28
asked Nov 16 at 23:06
Neppomuk
1581114
1581114
6
Yes, anything is possible with undefined behavior.
– melpomene
Nov 16 at 23:11
I am pretty sure you can abuse the language to do this on purpose (aka it's very obvious when you do it), I don't exactly recall how though. Maybe you are reading uninitialized memory (likely), corrupting the object memory (less likely) or encountering just another sort of weirdness in your real usecase - assuming your question is related to a real problem in a larger codebase.
– Asu
Nov 16 at 23:13
5
The private mechanism in C++ isn't a security system, and can be pretty trivially be got around. However, it's unlikely (though not impossible) that you can modify private member variables unintentionally.
– Neil Butterworth
Nov 16 at 23:19
2
Easy to do with a versioning problem. Old non-recompiled code uses a new class that is bigger.
– Hans Passant
Nov 17 at 0:31
3
If code like this leads to behaviour like you describe, you are most likely dealing with either a compiler bug or a hardware bug. Though one cannot exclude UB that occurs elsewhere weirdly interacting with this code. Another pissibility is gdb misidentifying the offending line. It is really hard to tell without seeing the whole picture.
– n.m.
Nov 18 at 16:45
|
show 5 more comments
6
Yes, anything is possible with undefined behavior.
– melpomene
Nov 16 at 23:11
I am pretty sure you can abuse the language to do this on purpose (aka it's very obvious when you do it), I don't exactly recall how though. Maybe you are reading uninitialized memory (likely), corrupting the object memory (less likely) or encountering just another sort of weirdness in your real usecase - assuming your question is related to a real problem in a larger codebase.
– Asu
Nov 16 at 23:13
5
The private mechanism in C++ isn't a security system, and can be pretty trivially be got around. However, it's unlikely (though not impossible) that you can modify private member variables unintentionally.
– Neil Butterworth
Nov 16 at 23:19
2
Easy to do with a versioning problem. Old non-recompiled code uses a new class that is bigger.
– Hans Passant
Nov 17 at 0:31
3
If code like this leads to behaviour like you describe, you are most likely dealing with either a compiler bug or a hardware bug. Though one cannot exclude UB that occurs elsewhere weirdly interacting with this code. Another pissibility is gdb misidentifying the offending line. It is really hard to tell without seeing the whole picture.
– n.m.
Nov 18 at 16:45
6
6
Yes, anything is possible with undefined behavior.
– melpomene
Nov 16 at 23:11
Yes, anything is possible with undefined behavior.
– melpomene
Nov 16 at 23:11
I am pretty sure you can abuse the language to do this on purpose (aka it's very obvious when you do it), I don't exactly recall how though. Maybe you are reading uninitialized memory (likely), corrupting the object memory (less likely) or encountering just another sort of weirdness in your real usecase - assuming your question is related to a real problem in a larger codebase.
– Asu
Nov 16 at 23:13
I am pretty sure you can abuse the language to do this on purpose (aka it's very obvious when you do it), I don't exactly recall how though. Maybe you are reading uninitialized memory (likely), corrupting the object memory (less likely) or encountering just another sort of weirdness in your real usecase - assuming your question is related to a real problem in a larger codebase.
– Asu
Nov 16 at 23:13
5
5
The private mechanism in C++ isn't a security system, and can be pretty trivially be got around. However, it's unlikely (though not impossible) that you can modify private member variables unintentionally.
– Neil Butterworth
Nov 16 at 23:19
The private mechanism in C++ isn't a security system, and can be pretty trivially be got around. However, it's unlikely (though not impossible) that you can modify private member variables unintentionally.
– Neil Butterworth
Nov 16 at 23:19
2
2
Easy to do with a versioning problem. Old non-recompiled code uses a new class that is bigger.
– Hans Passant
Nov 17 at 0:31
Easy to do with a versioning problem. Old non-recompiled code uses a new class that is bigger.
– Hans Passant
Nov 17 at 0:31
3
3
If code like this leads to behaviour like you describe, you are most likely dealing with either a compiler bug or a hardware bug. Though one cannot exclude UB that occurs elsewhere weirdly interacting with this code. Another pissibility is gdb misidentifying the offending line. It is really hard to tell without seeing the whole picture.
– n.m.
Nov 18 at 16:45
If code like this leads to behaviour like you describe, you are most likely dealing with either a compiler bug or a hardware bug. Though one cannot exclude UB that occurs elsewhere weirdly interacting with this code. Another pissibility is gdb misidentifying the offending line. It is really hard to tell without seeing the whole picture.
– n.m.
Nov 18 at 16:45
|
show 5 more comments
1 Answer
1
active
oldest
votes
After floating around the code line in question, I found out that the blunder was lying in the line before, which reads as follows:
last_levels [h] [l] = 0;
Unfortunately, h
can be < 0. In this case, some kinda exception (array index out of bounds) should be thrown, but unfortunately, it isn't (Does anybody know why?). The gdb gave me the wrong information of the overwrite of is_ready
to happen in the following line (Is this maybe a bug?), and I believed this without any criticism. As if this wasn't enough, this error made no problems until I changed my code in a completely different place!
This blunder has cost me quite much time, but now, at last, I know what its cause was, and I corrected it successfully. Thank you anyway for your hints and comments!
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53346531%2fcan-the-code-of-some-c-class-accidentally-overwrite-a-private-static-variable%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
After floating around the code line in question, I found out that the blunder was lying in the line before, which reads as follows:
last_levels [h] [l] = 0;
Unfortunately, h
can be < 0. In this case, some kinda exception (array index out of bounds) should be thrown, but unfortunately, it isn't (Does anybody know why?). The gdb gave me the wrong information of the overwrite of is_ready
to happen in the following line (Is this maybe a bug?), and I believed this without any criticism. As if this wasn't enough, this error made no problems until I changed my code in a completely different place!
This blunder has cost me quite much time, but now, at last, I know what its cause was, and I corrected it successfully. Thank you anyway for your hints and comments!
add a comment |
After floating around the code line in question, I found out that the blunder was lying in the line before, which reads as follows:
last_levels [h] [l] = 0;
Unfortunately, h
can be < 0. In this case, some kinda exception (array index out of bounds) should be thrown, but unfortunately, it isn't (Does anybody know why?). The gdb gave me the wrong information of the overwrite of is_ready
to happen in the following line (Is this maybe a bug?), and I believed this without any criticism. As if this wasn't enough, this error made no problems until I changed my code in a completely different place!
This blunder has cost me quite much time, but now, at last, I know what its cause was, and I corrected it successfully. Thank you anyway for your hints and comments!
add a comment |
After floating around the code line in question, I found out that the blunder was lying in the line before, which reads as follows:
last_levels [h] [l] = 0;
Unfortunately, h
can be < 0. In this case, some kinda exception (array index out of bounds) should be thrown, but unfortunately, it isn't (Does anybody know why?). The gdb gave me the wrong information of the overwrite of is_ready
to happen in the following line (Is this maybe a bug?), and I believed this without any criticism. As if this wasn't enough, this error made no problems until I changed my code in a completely different place!
This blunder has cost me quite much time, but now, at last, I know what its cause was, and I corrected it successfully. Thank you anyway for your hints and comments!
After floating around the code line in question, I found out that the blunder was lying in the line before, which reads as follows:
last_levels [h] [l] = 0;
Unfortunately, h
can be < 0. In this case, some kinda exception (array index out of bounds) should be thrown, but unfortunately, it isn't (Does anybody know why?). The gdb gave me the wrong information of the overwrite of is_ready
to happen in the following line (Is this maybe a bug?), and I believed this without any criticism. As if this wasn't enough, this error made no problems until I changed my code in a completely different place!
This blunder has cost me quite much time, but now, at last, I know what its cause was, and I corrected it successfully. Thank you anyway for your hints and comments!
answered Nov 23 at 10:08
Neppomuk
1581114
1581114
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53346531%2fcan-the-code-of-some-c-class-accidentally-overwrite-a-private-static-variable%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
6
Yes, anything is possible with undefined behavior.
– melpomene
Nov 16 at 23:11
I am pretty sure you can abuse the language to do this on purpose (aka it's very obvious when you do it), I don't exactly recall how though. Maybe you are reading uninitialized memory (likely), corrupting the object memory (less likely) or encountering just another sort of weirdness in your real usecase - assuming your question is related to a real problem in a larger codebase.
– Asu
Nov 16 at 23:13
5
The private mechanism in C++ isn't a security system, and can be pretty trivially be got around. However, it's unlikely (though not impossible) that you can modify private member variables unintentionally.
– Neil Butterworth
Nov 16 at 23:19
2
Easy to do with a versioning problem. Old non-recompiled code uses a new class that is bigger.
– Hans Passant
Nov 17 at 0:31
3
If code like this leads to behaviour like you describe, you are most likely dealing with either a compiler bug or a hardware bug. Though one cannot exclude UB that occurs elsewhere weirdly interacting with this code. Another pissibility is gdb misidentifying the offending line. It is really hard to tell without seeing the whole picture.
– n.m.
Nov 18 at 16:45