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
| Impact | Details |
|---|---|
| Other | Scope: Other Quality Degradation - Functions operate on wrong data, producing incorrect and unpredictable results. |
| Access Control | Scope: Access Control Gain Privileges or Assume Identity - Using wrong role or permission variables can grant unauthorized access. |
| Confidentiality | Scope: 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
- MITRE Corporation. "CWE-688: Function Call With Incorrect Variable or Reference as Argument." https://cwe.mitre.org/data/definitions/688.html
- CERT C Coding Standard. "EXP37-C. Call functions with the correct number and type of arguments."