Program: CWE-787
Project: CVE-2020-36402
Buggy source:
********************************
Solidity IR-based Codegen Changes
********************************

This section highlights the main differences between the old and the IR-based codegen,
along with the reasoning behind the changes and how to update affected code.

Semantic Only Changes
=====================

This section lists the changes that are semantic-only, thus potentially
hiding new and different behavior in existing code.

 * When storage structs are deleted, every storage slot that contains a member of the struct is set to zero entirely. Formally, padding space was left untouched.
Consequently, if the padding space within a struct is used to store data (e.g. in the context of a contract upgrade), you have to be aware that ``delete`` will now also clear the added member (while it wouldn't have been cleared in the past).

::
    // SPDX-License-Identifier: GPL-3.0
    pragma solidity >0.7.0;

    contract C {
        struct S {
            uint64 y;
            uint64 z;
        }
        S s;
        function f() public {
            // ...
            delete s;
            // s occupies only first 16 bytes of the 32 bytes slot
            // delete will write zero to the full slot
        }
    }

We have the same behavior for implicit delete, for example when array of structs is shortened.

 * The order of contract initialization has changed in case of inheritance.

The order used to be:
 - All state variables are zero-initialized at the beginning.
 - Evaluate base constructor arguments from most derived to most base contract.
 - Initialize all state variables in the whole inheritance hierarchy from most base to most derived.
 - Run the constructor, if present, for all contracts in the linearized hierarchy from most base to most derived.

New order:
 - All state variables are zero-initialized at the beginning.
 - Evaluate base constructor arguments from most derived to most base contract.
 - For every contract in order from most base to most derived in the linearized hierarchy execute:
     1. State variables are assigned value their initial values, if present at declaration.
     2. Constructor, if present.

This causes differences in some contracts, for example:
::
    // SPDX-License-Identifier: GPL-3.0
    pragma solidity >0.7.0;

    contract A {
        uint x;
        constructor() {
            x = 42;
        }
        function f() public view returns(uint256) {
            return x;
        }
    }
    contract B is A {
        uint public y = f();
    }

Previously, ``y`` would be set to 0. This is due to the fact that we would first initialize state variables: First, ``x`` is set to 0, and when initializing ``y``, ``f()`` would return 0 causing ``y`` to be 0 as well.
With the new rules, ``y`` will be set to 42. We first initialize ``x`` to 0, then call A's constructor which sets ``x`` to 42. Finally, when initializing ``y``, ``f()`` returns 42 causing ``y`` to be 42.


Fixed version (ground truth):
********************************
Solidity IR-based Codegen Changes
********************************

This section highlights the main differences between the old and the IR-based codegen,
along with the reasoning behind the changes and how to update affected code.

Semantic Only Changes
=====================

This section lists the changes that are semantic-only, thus potentially
hiding new and different behavior in existing code.

 * When storage structs are deleted, every storage slot that contains a member of the struct is set to zero entirely. Formally, padding space was left untouched.
Consequently, if the padding space within a struct is used to store data (e.g. in the context of a contract upgrade), you have to be aware that ``delete`` will now also clear the added member (while it wouldn't have been cleared in the past).

::
    // SPDX-License-Identifier: GPL-3.0
    pragma solidity >0.7.0;

    contract C {
        struct S {
            uint64 y;
            uint64 z;
        }
        S s;
        function f() public {
            // ...
            delete s;
            // s occupies only first 16 bytes of the 32 bytes slot
            // delete will write zero to the full slot
        }
    }

We have the same behavior for implicit delete, for example when array of structs is shortened.

 * The order of contract initialization has changed in case of inheritance.

The order used to be:
 - All state variables are zero-initialized at the beginning.
 - Evaluate base constructor arguments from most derived to most base contract.
 - Initialize all state variables in the whole inheritance hierarchy from most base to most derived.
 - Run the constructor, if present, for all contracts in the linearized hierarchy from most base to most derived.

New order:
 - All state variables are zero-initialized at the beginning.
 - Evaluate base constructor arguments from most derived to most base contract.
 - For every contract in order from most base to most derived in the linearized hierarchy execute:
     1. State variables are assigned their initial values, if present at declaration.
     2. Constructor, if present.

This causes differences in some contracts, for example:
::
    // SPDX-License-Identifier: GPL-3.0
    pragma solidity >0.7.0;

    contract A {
        uint x;
        constructor() {
            x = 42;
        }
        function f() public view returns(uint256) {
            return x;
        }
    }
    contract B is A {
        uint public y = f();
    }

Previously, ``y`` would be set to 0. This is due to the fact that we would first initialize state variables: First, ``x`` is set to 0, and when initializing ``y``, ``f()`` would return 0 causing ``y`` to be 0 as well.
With the new rules, ``y`` will be set to 42. We first initialize ``x`` to 0, then call A's constructor which sets ``x`` to 42. Finally, when initializing ``y``, ``f()`` returns 42 causing ``y`` to be 42.