JDK-8279566 : Improve local variable initialisation in NetworkInterface.c
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.net
  • Affected Version: 18
  • Priority: P3
  • Status: In Progress
  • Resolution: Unresolved
  • OS: windows
  • CPU: x86
  • Submitted: 2022-01-06
  • Updated: 2022-02-21
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
tbdUnresolved
Related Reports
Relates :  
Relates :  
Description
It has been found that while testing in an IPv6 only environment on Windows i.e. a system on which the command " netsh interface ipv4 uninstall"  has been executed to disable IPv4 stack functionality, that a simple sanity check which executes the InetAddress.getLoopbackAddress results in the program silently crashing.

This has been found to be due to a local pointer variable not being properly initialised, and it being subsequently freed in the NetworkInterface.c code

functions:
Java_java_net_NetworkInterface_boundInetAddress0

        MIB_IPADDRTABLE *tableP;
        if ((lookupIPAddrTable(env, &tableP) >= 0) && (tableP != NULL)) {
            for (i = 0; i < tableP->dwNumEntries; i++) {
                if (tableP->table[i].dwAddr != 0 &&
                    (unsigned long)addr == ntohl(tableP->table[i].dwAddr)) {
                    found = JNI_TRUE;
                    break;
                }
            }
        }
        if (tableP != NULL) {
          free(tableP);
        }

Note tableP is not initialised to NULL and is a local variable, therefore its initial value is determined by what's on the stack. As such, it would be appropriate to initialise tableP to NULL

MIB_IPADDRTABLE *tableP = NULL;

lookupIPAddrTable - sanitise tablePP return value (NULL) for error cases

int lookupIPAddrTable(JNIEnv *env, MIB_IPADDRTABLE **tablePP)
{
    MIB_IPADDRTABLE *tableP;
    ULONG size;
    DWORD ret;
    /*
     * Use GetIpAddrTable to enumerate the IP Addresses
     */
    size = sizeof(MIB_IPADDRTABLE);
    tableP = (MIB_IPADDRTABLE *)malloc(size);
    if (tableP == NULL) {
        JNU_ThrowOutOfMemoryError(env, "Native heap allocation failure");
        // SHOULD ADD  have *tablePP = NULL;
        return -1;
    }

    ret = GetIpAddrTable(tableP, &size, FALSE);
    if (ret == ERROR_INSUFFICIENT_BUFFER) {
        MIB_IPADDRTABLE * newTableP = (MIB_IPADDRTABLE *)realloc(tableP, size);
        if (newTableP == NULL) {
            free(tableP);
            JNU_ThrowOutOfMemoryError(env, "Native heap allocation failure");
        // SHOULD ADD  have *tablePP = NULL;
            return -1;
        }
        tableP = newTableP;

        ret = GetIpAddrTable(tableP, &size, FALSE);
    }
    if (ret != NO_ERROR) {
        if (tableP != NULL) {
            free(tableP);
        }
        switch (ret) {
            case ERROR_INVALID_PARAMETER:
                JNU_ThrowInternalError(env,
                    "IP Helper Library GetIpAddrTable function failed: "
                    "invalid parameter");
                break;
            default:
                SetLastError(ret);
                JNU_ThrowByNameWithMessageAndLastError(env,
                    JNU_JAVANETPKG "SocketException",
                    "IP Helper Library GetIpAddrTable function failed");
                break;
        }
        // this different error code is to handle the case when we call
        // GetIpAddrTable in pure IPv6 environment
        // SHOULD ADD  have *tablePP = NULL;
        return -2;
    }
    *tablePP = tableP;
    return 0;
}


Note that in lookupIPAddrTable a that the out parameter tablePP is assigned only for a successful return, all error returns leave the variable in its initial inout state.