>>87707840

Undefined behavior is fine if you're familiar with the underlying context, as at that point it becomes undocumented behavior rather than undefined behavior. For a notable example, if you know you're on x86 you can safely push an address on the stack and ret to it, regardless of compiler quirks. (Cleanup afterwards can get messy though.)

Essentially, when you call a function the system needs to know where to resume execution after completing the function. That 'return address' is stored at a certain place in memory. If that function however calls another function, you need to store another return address. In the memory section containing the earlier return address, the new return address is added in the next available spot ('stacked on top of the previous data'). When going through returns (the internal implementation of 'end of function'), it keeps removing the top return address (popping) to resume execution of the parent function with every return. Think of it like stacking blocks on a block tower, then removing them again starting from the top.

In addition to the return addresses, the stack also contains some other data (most notably, function arguments and local variables).

The Kind of Tired That Sleep Won’t Fix Shirt $21.68

Black Rifle Cuck Company, Conservative Humor Shirt $21.68

The Kind of Tired That Sleep Won’t Fix Shirt $21.68

  1. 2 years ago
    Anonymous

    Sorry for the late response, I was debugging an issue that kept me from posting.

  2. 2 years ago
    Anonymous

    >Undefined behavior is fine if you're familiar with the underlying context, as at that point it becomes undocumented behavior rather than undefined behavior.
    blatantly wrong, take meds schizo

    • 2 years ago
      Anonymous

      You also never assume an int is 4 bytes then, I take it? Because the language does not specify it as such (and indeed some obscure implementations have ints that aren't 4 bytes) so any code relying on that assumption (which is always true in any environment you and I work in) exhibits 'undefined behavior'. Which in context is very much defined, just not documented as such.

      • 2 years ago
        Anonymous

        >troony assumes an int is 4 bytes instead of using sized integer types or at least fricking asserting sizeof (int) == 4
        have a nice day moronic Black person

        • 2 years ago
          Anonymous

          Overly defensive coding causes more issues than it solves.

          • 2 years ago
            Anonymous

            >coding
            >overly defensive
            have a nice day troony

          • 2 years ago
            Anonymous

            Sorry but if you don't know to use int32_t whenever you need an exactly 4 byte integer and not more, then you don't know C.
            I'm not sure, but I don't think you ever actually need to depend in UB. The C standard makes a difference between undefined behavior and implementation-defined behavior. Integer type length is implementation defined.

          • 2 years ago
            Anonymous

            int32_t is cleaner, but that wasn't what I was talking about. Given that you have an int (e.g. in code you cannot change for whatever reason) you can assume it will be 4 bytes if you know the code will only ever be used on x86/x86_64. To check for it like

            >troony assumes an int is 4 bytes instead of using sized integer types or at least fricking asserting sizeof (int) == 4
            have a nice day moronic Black person

            implied is moronic.

            >I don't think you ever actually need to depend in UB.
            You do when you perform low-level black magic, e.g. code injection.

          • 2 years ago
            Anonymous

            yeah it all depends, this is pretty fair. the cargo cult of "C code MUST BE portable" is moronic; C code should work on the platform you're supporting. that's it!

          • 2 years ago
            Anonymous

            Just because it's not portable it doesn't mean it invokes UB.
            They are inherently different things.
            UB generally means that you are doing things you shouldn't be doing even if you don't care about portability. Because for example a compiler update, or future changes in some other part of the code could change how the compiler treats those UB parts of the code and break your program.

          • 2 years ago
            Anonymous

            Well if you cannot change the code then you wouldn't be adding asserts obviously.
            If you have a shared library built from code that uses int then yeah it doesn't matter, once the binary is built and you know whether the argument to the exported function is 32 or 64 bits. But again, that's not UB.
            >You do when you perform low-level black magic, e.g. code injection.
            What do you mean by "code injection". You mean patching a running binary? In that case it isn't UB, no. You are just writing to bytes in memory, no different from the perspective of the C compiler than, say, modifying a string.

          • 2 years ago
            Anonymous

            >What do you mean by "code injection". You mean patching a running binary? In that case it isn't UB, no. You are just writing to bytes in memory
            First of all, you patch a process - a binary is what it is on disk, a process is spawned using it and a lot of transformation is involved, it doesn't just map it directly into memory.

            Anyhow, what I'm referring to is more complicated stuff like hooking, where you overwrite the start of a function to jump to your own code. As you need to be able to read the original function arguments and eventually restore the program to a state where the caller is unaware anything happened and thinks the callee just finished executing, low level manipulation is required that depends on specific implementations not always defined by the spec.

          • 2 years ago
            Anonymous

            >a process is spawned using it and a lot of transformation is involved
            There isn't that much transformation... The .text will be the same on memory as it was on the file
            >Anyhow, what I'm referring to is more complicated stuff like hooking, where you overwrite the start of a function to jump to your own code. As you need to be able to read the original function arguments and eventually restore the program to a state where the caller is unaware anything happened and thinks the callee just finished executing, low level manipulation is required that depends on specific implementations not always defined by the spec.
            Sure, what I'm saying is that's not UB. Of course it won't be defined in the spec, assembly isn't defined in the C spec, obviously.
            Once the binary was generated, you cannot possibly invoke UB because what you have is not C code anymore.
            If both the program you are modifying and the injected program didn't have UB at the time of compilation, that's it. Nothing you do at runtime after everything was compiled could possibly violate the C spec because you aren't dealing with C code anymore.
            Binary code doesn't have the concept of functions btw. x86 has procedures that may or may not map to C functions. Other assembly languages may not even have procedures.

          • 2 years ago
            Anonymous

            >The .text will be the same on memory as it was on the file
            It will be at a different offset to what preceded it than it was in the binary, and things like relocation occur. Depending on where you draw the line between initialization and execution libraries may also modify it at loadtime in unusual cases.

            You could move all of your black magic to the assembly part and completely set it up to look like a normal function call to minimize UB, in which case you TECHNICALLY have no UB as you moved all assumptions to the function signatures of your code. But you'd only be fooling yourself with such pedantry; you're still at risk of UB-like symptoms if your assumptions are incorrect and the injected code calls your C code incorrectly (or worse, it crashes inside the injected ASM), you've only made it harder to debug.

            Arguing that procedures are not functions is like arguing in other languages that methods are not functions. They're all different implementations of the concept of a function. The call/ret system just allows for more black magic than other systems.

            You can't just post a shitty thread with e-girls as OP without posting more e-girl pics
            frick you op

            The dicky is over at

            [...]

            , but the janny is allergic to them and won't let us have a decent on-topic conversation if any is posted.

          • 2 years ago
            Anonymous

            What you call "UB like behavior" in my opinion would just be a mistake in the program.
            The reason I'm saying functions don't map well to procedures is because of inlining and other compiler optimizations.

          • 2 years ago
            Anonymous

            >I'm not sure, but I don't think you ever actually need to depend in UB.
            All kernels depend on it. Linux for example mandates building with `-fno-strict-aliasing`.

            https://www.yodaiken.com/2021/10/06/plos-2021-paper-how-iso-c-became-unusable-for-operating-system-development/

  3. 2 years ago
    Anonymous

    >Undefined behavior is fine
    for whom?

  4. 2 years ago
    Anonymous

    You can't just post a shitty thread with e-girls as OP without posting more e-girl pics
    frick you op

  5. 2 years ago
    Anonymous

    nakadashi, marry and nakadashi every night, nakadashi

  6. 2 years ago
    Anonymous

    >Think of it like stacking blocks on a block tower
    imagine being this moronic

Your email address will not be published. Required fields are marked *