Main Content

CWE Rule 781

Improper Address Validation in IOCTL with METHOD_NEITHER I/O Control Code

Since R2026b

Description

The product defines an IOCTL that uses METHOD_NEITHER for I/O, but it does not validate or incorrectly validates the addresses that are provided

Polyspace Implementation

Polyspace® checks for the issue IOCTL with METHOD_NEITHER

Examples

expand all

Issue

The issue occurs when IOCTL code is defined or used with the METHOD_NEITHER option.

Risk

Using METHOD_NEITHER requires the IOCTL code to validate the input addresses. If the validation is incorrectly done, attackers can execute malicious code and perform denial of service attacks by supplying arbitrary memory addresses.

Fix

Avoid using METHOD_NEITHER. Use methods that effectively control the buffer size, such as METHOD_BUFFERED, METHOD_IN_DIRECT, or METHOD_OUT_DIRECT

Example

This code demonstrates how IOCTL can be used with transfer methods. Polyspace reports a violation when IOCTL is used with METHOD_NEITHER

#include <stdlib.h>
#include <stdbool.h>

typedef int HANDLE;
typedef long DWORD;
typedef void *LPVOID;
typedef long *LPDWORD;
typedef void *LPOVERLAPPED;

extern bool DeviceIoControl(
    HANDLE deviceHandle,
    DWORD ioControlCode,
    LPVOID inputBuffer,
    DWORD inputBufferSize,
    LPVOID outputBuffer,
    DWORD outputBufferSize,
    LPDWORD bytesReturned,
    LPOVERLAPPED overlapped
);

#define CTL_CODE(DeviceType, Function, Method, Access) ( \
    ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
)

#define METHOD_BUFFERED   0
#define METHOD_IN_DIRECT  1
#define METHOD_OUT_DIRECT 2
#define METHOD_NEITHER    3

DWORD getDeviceType() {
    return 1;
}

void non_compliant() {
    HANDLE deviceHandle = 1234;
    int inputBuffer[20], outputBuffer[32];
    long bytesReturned;
    DWORD ioctlCode = CTL_CODE(getDeviceType(), 8, METHOD_NEITHER, 1);

    DeviceIoControl( //Noncompliant
        deviceHandle,
        ioctlCode,
        inputBuffer, sizeof(inputBuffer),
        outputBuffer, sizeof(outputBuffer),
        &bytesReturned,
        NULL
    );
}

Correction

The corrected approach replaces METHOD_NEITHER with METHOD_BUFFERED.

#include <stdlib.h>
#include <stdbool.h>

typedef int HANDLE;
typedef long DWORD;
typedef void *LPVOID;
typedef long *LPDWORD;
typedef void *LPOVERLAPPED;

extern bool DeviceIoControl(
    HANDLE deviceHandle,
    DWORD ioControlCode,
    LPVOID inputBuffer,
    DWORD inputBufferSize,
    LPVOID outputBuffer,
    DWORD outputBufferSize,
    LPDWORD bytesReturned,
    LPOVERLAPPED overlapped
);

#define CTL_CODE(DeviceType, Function, Method, Access) ( \
    ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
)

#define METHOD_BUFFERED   0
#define METHOD_IN_DIRECT  1
#define METHOD_OUT_DIRECT 2
#define METHOD_NEITHER    3

DWORD getDeviceType() {
    return 1;
}

void compliant() {
    HANDLE deviceHandle = 1234;
    int inputBuffer[20], outputBuffer[32];
    long bytesReturned;
    DWORD ioctlCode = CTL_CODE(getDeviceType(), 8, METHOD_BUFFERED, 1);

    DeviceIoControl( //Compliant
        deviceHandle,
        ioctlCode,
        inputBuffer, sizeof(inputBuffer),
        outputBuffer, sizeof(outputBuffer),
        &bytesReturned,
        NULL
    );
}

Check Information

Category: Others
PQL Name: std.cwe_native.R781

Version History

Introduced in R2026b