Can the code of some C++ class accidentally overwrite a private static variable of another class?












0














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.










share|improve this question




















  • 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
















0














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.










share|improve this question




















  • 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














0












0








0







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.










share|improve this question















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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














  • 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












1 Answer
1






active

oldest

votes


















0














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!






share|improve this answer





















    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
    });


    }
    });














    draft saved

    draft discarded


















    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









    0














    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!






    share|improve this answer


























      0














      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!






      share|improve this answer
























        0












        0








        0






        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!






        share|improve this answer












        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!







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 23 at 10:08









        Neppomuk

        1581114




        1581114






























            draft saved

            draft discarded




















































            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.




            draft saved


            draft discarded














            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





















































            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







            Popular posts from this blog

            Contact image not getting when fetch all contact list from iPhone by CNContact

            count number of partitions of a set with n elements into k subsets

            A CLEAN and SIMPLE way to add appendices to Table of Contents and bookmarks