Function Call With Incorrect Variable or Reference as Argument

Description

Function Call With Incorrect Variable or Reference as Argument is a programming error where code calls a function with the wrong variable or reference as an argument. Unlike type or value errors, this occurs when a programmer accidentally passes a different variable than intended—often due to typos, copy-paste errors, or confusion between similarly named variables. The variable passed may have the correct type and even a reasonable value, but it's simply not the variable the function should be operating on. This can cause functions to process the wrong data with serious security implications.

Risk

Passing the wrong variable to functions creates serious security risks that are difficult to detect. Authorization checks using wrong role arrays may grant inappropriate access. Security functions operating on wrong data structures may provide false validation. Memory operations on wrong buffers can cause corruption or information leakage. The risk is amplified because these bugs often appear syntactically and type-correct, passing compiler checks and superficial code review. In security contexts, using the wrong variable—like passing admin roles instead of user roles—can completely subvert access control systems.

Solution

Use meaningful and distinct variable names that clearly indicate purpose. Avoid naming variables similarly to global or static variables. Minimize variable scope to reduce the chance of using wrong variables. Use IDE features that highlight variable usage. Conduct careful code reviews specifically looking for copy-paste errors and variable name confusion. Implement comprehensive unit tests that verify functions operate on the intended data. Use static analysis tools that can detect suspicious variable usage patterns. Consider using named parameters where language supports them.

Common Consequences

ImpactDetails
OtherScope: Other

Quality Degradation - Functions operate on wrong data, producing incorrect and unpredictable results.
Access ControlScope: Access Control

Gain Privileges or Assume Identity - Using wrong role or permission variables can grant unauthorized access.
ConfidentialityScope: Confidentiality

Read Application Data - Processing wrong buffers or data structures may expose sensitive information.

Example Code

Vulnerable Code

// Vulnerable: Using static admin roles instead of user's actual roles
public class VulnerableAccessControl {

    // Static admin role array for reference
    private static final String[] ADMIN_ROLES = {"admin", "superuser", "root"};

    public boolean checkAccess(String resource, String[] userRoles) {
        // Vulnerable: Accidentally using ADMIN_ROLES instead of userRoles!
        return accessGranted(resource, ADMIN_ROLES);  // WRONG VARIABLE!
        // Every user gets admin-level access check
        // Should be: return accessGranted(resource, userRoles);
    }

    private boolean accessGranted(String resource, String[] roles) {
        for (String role : roles) {
            if (hasPermission(role, resource)) {
                return true;
            }
        }
        return false;
    }
}

// Vulnerable: Copy-paste error with similar variable names
public class VulnerableCopyPaste {

    public void processUserData(User sourceUser, User targetUser) {
        // Validate source user's permissions
        validatePermissions(sourceUser);

        // Vulnerable: Copy-paste error - using sourceUser twice
        copyData(sourceUser, sourceUser);  // WRONG! Should be targetUser
        // Data copied from source to itself instead of to target
    }

    public void updateRecords(Record oldRecord, Record newRecord) {
        // Vulnerable: Swapped variables
        database.delete(newRecord);  // WRONG! Deletes new instead of old
        database.insert(oldRecord);  // WRONG! Re-inserts old instead of new
    }
}
// Vulnerable: Wrong buffer used in kernel code (CVE-2005-2548 pattern)
#include <string.h>

struct packet_header {
    int type;
    int length;
    char data[256];
};

struct packet_header global_header;  // Global template

// Vulnerable: Wrong variable in first argument
void vulnerable_init_packet(struct packet_header* user_packet) {
    // Vulnerable: Using global_header as destination instead of user_packet
    memcpy(&global_header, &global_header, sizeof(struct packet_header));
    // Copies global to itself - user_packet unchanged!
    // Should be: memcpy(user_packet, &global_header, sizeof(...))
}

// Vulnerable: Wrong pointer causing NULL dereference
void vulnerable_process(struct data* input, struct data* output) {
    struct data* temp = NULL;

    if (validate(input)) {
        temp = allocate_data();
        // ... processing ...
    }

    // Vulnerable: Using 'input' where 'temp' was intended
    if (input != NULL) {  // Should check 'temp'
        copy_data(output, input);  // May use unvalidated temp
    }
}
# Vulnerable: Using wrong list in loop
def vulnerable_batch_process(pending_items, completed_items):
    processed = []

    # Vulnerable: Iterating over completed_items instead of pending_items
    for item in completed_items:  # WRONG LIST!
        result = process(item)
        processed.append(result)

    # Re-processes already completed items, misses pending ones
    return processed

# Vulnerable: Wrong dictionary in security context
class VulnerableAuth:

    def __init__(self):
        self.valid_tokens = {}  # User tokens
        self.revoked_tokens = {}  # Invalidated tokens

    def validate_token(self, token):
        # Vulnerable: Checking wrong dictionary
        if token in self.revoked_tokens:  # WRONG! Should check valid_tokens
            return True  # Accepts revoked tokens!
        return False

# Vulnerable: Similar variable names
def calculate_discount(base_price, discount_rate, discounted_price):
    # Vulnerable: Using discounted_price instead of base_price
    calculated = discounted_price * (1 - discount_rate)  # WRONG!
    # Applies discount to already-discounted price
    # Should use base_price
    return calculated
// Vulnerable: Using wrong object property
function vulnerableUserUpdate(currentUser, newData) {
    const adminDefaults = {
        role: 'admin',
        permissions: ['all']
    };

    const userDefaults = {
        role: 'user',
        permissions: ['read']
    };

    // Vulnerable: Using adminDefaults instead of userDefaults
    return Object.assign({}, adminDefaults, newData);  // WRONG!
    // Regular users get admin defaults applied
}

// Vulnerable: Wrong array in splice
function vulnerableRemoveItem(activeList, archiveList, itemId) {
    const index = activeList.findIndex(item => item.id === itemId);

    if (index !== -1) {
        // Vulnerable: Removing from archiveList instead of activeList
        archiveList.splice(index, 1);  // WRONG ARRAY!
        // Removes wrong item from wrong list
    }
}

Fixed Code

// Fixed: Using correct variables with clear naming
public class SecureAccessControl {

    private static final String[] ADMIN_ROLES = {"admin", "superuser", "root"};

    public boolean checkAccess(String resource, String[] requestingUserRoles) {
        // Fixed: Using correctly named parameter
        return accessGranted(resource, requestingUserRoles);
    }

    // Alternative: Make method harder to misuse
    public boolean checkAccessForUser(String resource, User user) {
        String[] userRoles = user.getRoles();  // Get roles from user object
        return accessGranted(resource, userRoles);
    }

    private boolean accessGranted(String resource, String[] roles) {
        for (String role : roles) {
            if (hasPermission(role, resource)) {
                return true;
            }
        }
        return false;
    }
}

// Fixed: Distinct variable names prevent copy-paste errors
public class SecureCopyPaste {

    public void processUserData(User fromUser, User toUser) {
        // Fixed: Distinct names make errors obvious
        validatePermissions(fromUser);
        copyData(fromUser, toUser);
    }

    public void updateRecords(Record recordToDelete, Record recordToInsert) {
        // Fixed: Names indicate purpose
        database.delete(recordToDelete);
        database.insert(recordToInsert);
    }
}
// Fixed: Correct variables with clear documentation
#include <string.h>

struct packet_header {
    int type;
    int length;
    char data[256];
};

static const struct packet_header DEFAULT_HEADER = {0, 0, {0}};

// Fixed: Correct destination variable
void secure_init_packet(struct packet_header* dest_packet) {
    // Fixed: Copy from template TO destination
    memcpy(dest_packet, &DEFAULT_HEADER, sizeof(struct packet_header));
}

// Fixed: Correct pointer with clear naming
void secure_process(struct data* input_data, struct data* output_data) {
    struct data* processed_temp = NULL;

    if (validate(input_data)) {
        processed_temp = allocate_data();
        // ... processing ...
    }

    // Fixed: Check the correct variable
    if (processed_temp != NULL) {
        copy_data(output_data, processed_temp);
        free_data(processed_temp);
    }
}

// Use const to prevent accidental modification
void init_from_template(struct packet_header* dest,
                        const struct packet_header* template) {
    // template is const - can't accidentally use as destination
    memcpy(dest, template, sizeof(struct packet_header));
}
# Fixed: Clear variable naming
def secure_batch_process(items_to_process, already_completed):
    processed = []

    # Fixed: Clear name indicates intent
    for item in items_to_process:
        result = process(item)
        processed.append(result)

    return processed

# Fixed: Explicit validation logic
class SecureAuth:

    def __init__(self):
        self.active_tokens = {}
        self.revoked_tokens = {}

    def validate_token(self, token):
        # Fixed: Explicit two-step validation
        is_active = token in self.active_tokens
        is_revoked = token in self.revoked_tokens

        # Token must be active AND not revoked
        return is_active and not is_revoked

# Fixed: Unambiguous parameter names
def calculate_discount(original_price, discount_percentage, existing_discount=0):
    # Fixed: Clear which price to use
    price_before_discount = original_price
    calculated = price_before_discount * (1 - discount_percentage)
    return calculated
// Fixed: Explicit variable selection
function secureUserUpdate(currentUser, newData, isAdmin = false) {
    const adminDefaults = {
        role: 'admin',
        permissions: ['all']
    };

    const userDefaults = {
        role: 'user',
        permissions: ['read']
    };

    // Fixed: Explicit selection based on condition
    const defaultsToUse = isAdmin ? adminDefaults : userDefaults;
    return Object.assign({}, defaultsToUse, newData);
}

// Fixed: Operate on correct array with validation
function secureRemoveItem(sourceList, targetList, itemId) {
    const index = sourceList.findIndex(item => item.id === itemId);

    if (index !== -1) {
        // Fixed: Remove from source, optionally move to target
        const [removed] = sourceList.splice(index, 1);
        if (targetList) {
            targetList.push(removed);  // Archive if target provided
        }
    }
}

// Best practice: Use object parameters to prevent variable confusion
function updateItem({ fromList, toList, itemId }) {
    // Named parameters make it clear which is which
    const index = fromList.findIndex(item => item.id === itemId);
    if (index !== -1) {
        const [item] = fromList.splice(index, 1);
        toList.push(item);
    }
}

CVE Examples

  • CVE-2005-2548: Linux kernel code specified the wrong variable in an initial argument, resulting in a NULL pointer dereference vulnerability.
  • CVE-2006-1052: Wrong variable used in comparison leading to authentication bypass.

References

  1. MITRE Corporation. "CWE-688: Function Call With Incorrect Variable or Reference as Argument." https://cwe.mitre.org/data/definitions/688.html
  2. CERT C Coding Standard. "EXP37-C. Call functions with the correct number and type of arguments."