Audit the following candidate code to determine whether it presents a real vulnerability.
This sample may come from a noisy retrieval or transformation stage, so reason from the supplied code and context rather than assuming the label.

Repository: git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux
Language: C
File: net/ipv4/tcp_input.c
Function: tcp_cwnd_reduction

Call path: tcp_enter_cwr (net/ipv4/tcp_input.c) → tcp_init_cwnd_reduction (net/ipv4/tcp_input.c) → tcp_cwnd_reduction (net/ipv4/tcp_input.c) → tcp_try_keep_open (net/ipv4/tcp_input.c) → tcp_process_loss (net/ipv4/tcp_input.c) → tcp_fastretrans_alert (net/ipv4/tcp_input.c)

### Primary Function

```c
static void tcp_cwnd_reduction(struct sock *sk, const int prior_unsacked,
				       int fast_rexmit, int flag)
{
	struct tcp_sock *tp = tcp_sk(sk);
	int sndcnt = 0;
	int delta = tp->snd_ssthresh - tcp_packets_in_flight(tp);
	int newly_acked_sacked = prior_unsacked -
				 (tp->packets_out - tp->sacked_out);

	if (newly_acked_sacked <= 0 || WARN_ON_ONCE(!tp->prior_cwnd))
		return;

	tp->prr_delivered += newly_acked_sacked;
	if (delta < 0) {
		u64 dividend = (u64)tp->snd_ssthresh * tp->prr_delivered +
			       tp->prior_cwnd - 1;
		sndcnt = div_u64(dividend, tp->prior_cwnd) - tp->prr_out;
	} else if ((flag & FLAG_RETRANS_DATA_ACKED) &&
		   !(flag & FLAG_LOST_RETRANS)) {
		sndcnt = min_t(int, delta,
			       max_t(int, tp->prr_delivered - tp->prr_out,
				     newly_acked_sacked) + 1);
	} else {
		sndcnt = min(delta, newly_acked_sacked);
	}
	sndcnt = max(sndcnt, (fast_rexmit ? 1 : 0));
	tp->snd_cwnd = tcp_packets_in_flight(tp) + sndcnt;
}
```

### Cross-File Context

[tcp_init_cwnd_reduction — helper — net/ipv4/tcp_input.c:2458-2470]
```c
static void tcp_init_cwnd_reduction(struct sock *sk)
{
	struct tcp_sock *tp = tcp_sk(sk);

	tp->high_seq = tp->snd_nxt;
	tp->tlp_high_seq = 0;
	tp->snd_cwnd_cnt = 0;
	tp->prior_cwnd = tp->snd_cwnd;
	tp->prr_delivered = 0;
	tp->prr_out = 0;
	tp->snd_ssthresh = inet_csk(sk)->icsk_ca_ops->ssthresh(sk);
	tcp_ecn_queue_cwr(tp);
}
```

[tcp_packets_in_flight — function — include/net/tcp.h:997-1001]
```c
static inline unsigned int tcp_packets_in_flight(const struct tcp_sock *tp)
{
	return tp->packets_out - tcp_left_out(tp) + tp->retrans_out;
}
```

[div_u64 — function — include/linux/math64.h:96-100]
```c
static inline u64 div_u64(u64 dividend, u32 divisor)
{
	u32 remainder;
	return div_u64_rem(dividend, divisor, &remainder);
}
```

[WARN_ON_ONCE — macro — include/asm-generic/bug.h:109-118]
WARN_ON_ONCE → #define WARN_ON_ONCE(condition) ({ \ static bool __section(.data.unlikely) __warned; \ int __ret_warn_once = !!(condition); \ \ if (unlikely(__ret_warn_once)) \ if (WARN_ON(!__warned)) \ __warned = true; \ unlikely(__ret_warn_once); \ })  (include/asm-generic/bug.h:109-118)

[struct tcp_sock — struct — include/linux/tcp.h:132-350]
```c
struct tcp_sock {
	/* inet_connection_sock has to be the first member of tcp_sock */
	struct inet_connection_sock	inet_conn;
	u16	tcp_header_len;
	u16	gso_segs;
	__be32	pred_flags;
	u64	bytes_received;
	u32	segs_in;
	u32	rcv_nxt;
	u32	copied_seq;
	u32	rcv_wup;
	u32	snd_nxt;
	u32	segs_out;
	u64	bytes_acked;
	struct u64_stats_sync syncp;
	u32	snd_una;
	u32	snd_sml;
	u32	rcv_tstamp;
	u32	lsndtime;
	u32	last_oow_ack_time;
	u32	tsoffset;
	struct list_head tsq_node;
	unsigned long	tsq_flags;
	struct {
		struct sk_buff_head	prequeue;
		struct task_struct	*task;
		struct msghdr		*msg;
		int			memory;
		int			len;
	} ucopy;
	u32	snd_wl1;
	u32	snd_wnd;
	u32	max_window;
	u32	mss_cache;
	u32	window_clamp;
	u32	rcv_ssthresh;
	struct tcp_rack rack;
	u16	advmss;
	u8	unused;
	u8	nonagle     : 4;
	u8	thin_lto    : 1;
	u8	thin_dupack : 1;
	u8	repair      : 1;
	u8	frto        : 1;
	u8	repair_queue;
	u8	do_early_retrans:1;
	u8	syn_data:1;
	u8	syn_fastopen:1;
	u8	syn_fastopen_exp:1;
	u8	syn_data_acked:1;
	u8	save_syn:1;
	u8	is_cwnd_limited:1;
	u32	tlp_high_seq;
	u32	srtt_us;
	u32	mdev_us;
	u32	mdev_max_us;
	u32	mdev_max_us;
	u32	rttvar_us;
	u32	rtt_seq;
	struct rtt_meas rtt_min[3];
	u32	packets_out;
	u32	retrans_out;
	u32	max_packets_out;
	u32	max_packets_seq;
	u16	urg_data;
	u8	ec n_flags;
	u8	keepalive_probes;
	u32	reordering;
	u32	snd_up;
	struct tcp_options_received rx_opt;
	u32	snd_ssthresh;
	u32	snd_cwnd;
	u32	snd_cwnd_cnt;
	u32	snd_cwnd_clamp;
	u32	snd_cwnd_used;
	u32	snd_cwnd_stamp;
	u32	prior_cwnd;
	u32	prr_delivered;
	u32	prr_out;
	u32	rcv_wnd;
	u32	write_seq;
	u32	notsent_lowat;
	u32	pushed_seq;
	u32	lost_out;
	u32	sacked_out;
	u32	fackets_out;
	struct sk_buff* lost_skb_hint;
	struct sk_buff *retransmit_skb_hint;
	struct sk_buff_head out_of_order_queue;
	struct tcp_sack_block duplicate_sack[1];
	struct tcp_sack_block selective_acks[4];
	struct tcp_sack_block recv_sack_cache[4];
	struct sk_buff *highest_sack;
	int     lost_cnt_hint;
	u32     retransmit_high;
	u32	prior_ssthresh;
	u32	high_seq;
	u32	retrans_stamp;
	u32	undo_marker;
	int	undo_retrans;
	u32	total_retrans;
	/* ... more fields ... */
}
```

[FLAG_RETRANS_DATA_ACKED — constant — net/ipv4/tcp_input.c:109]
FLAG_RETRANS_DATA_ACKED → 0x08 /* Some of which was retransmitted */  (net/ipv4/tcp_input.c:109)

[FLAG_LOST_RETRANS — constant — net/ipv4/tcp_input.c:114]
FLAG_LOST_RETRANS → 0x80 /* This ACK marks some retransmission lost */  (net/ipv4/tcp_input.c:114)

Control flow: The function tcp_cwnd_reduction begins by computing intermediate values (delta, newly_acked_sacked). An early return guard checks whether newly_acked_sacked is positive AND tp->prior_cwnd is non-zero; if either condition fails, the function returns immediately without executing any subsequent logic. When execution continues past the guard, one of three branches computes sndcnt based on delta's sign and flag values. In the delta < 0 branch, div_u64 is called with tp->prior_cwnd as divisor. All three branches flow to updating tp->snd_cwnd as the final operation.

Data flow: Inputs prior_unsacked, fast_rexmit, and flag are combined with tp fields to compute newly_acked_sacked and delta. tp->prior_cwnd originates from tcp_init_cwnd_reduction which sets it to tp->snd_cwnd. The newly_acked_sacked value is added to tp->prr_delivered. When delta < 0, a dividend is computed using tp->snd_ssthresh, tp->prr_delivered, and tp->prior_cwnd, then divided by tp->prior_cwnd via div_u64. The resulting sndcnt (constrained by fast_rexmit and delta logic) is added to tcp_packets_in_flight(tp) to set tp->snd_cwnd.

Verdict: Not Vulnerable

Reviewed region:
[net/ipv4/tcp_input.c]
```c
static void tcp_cwnd_reduction(struct sock *sk, const int prior_unsacked,
				       int fast_rexmit, int flag)
{
	struct tcp_sock *tp = tcp_sk(sk);
	int sndcnt = 0;
	int delta = tp->snd_ssthresh - tcp_packets_in_flight(tp);
	int newly_acked_sacked = prior_unsacked -
				 (tp->packets_out - tp->sacked_out);

	if (newly_acked_sacked <= 0 || WARN_ON_ONCE(!tp->prior_cwnd))
		return;

	tp->prr_delivered += newly_acked_sacked;
	if (delta < 0) {
		u64 dividend = (u64)tp->snd_ssthresh * tp->prr_delivered +
			       tp->prior_cwnd - 1;
		sndcnt = div_u64(dividend, tp->prior_cwnd) - tp->prr_out;
	} else if ((flag & FLAG_RETRANS_DATA_ACKED) &&
		   !(flag & FLAG_LOST_RETRANS)) {
		sndcnt = min_t(int, delta,
			       max_t(int, tp->prr_delivered - tp->prr_out,
				     newly_acked_sacked) + 1);
	} else {
		sndcnt = min(delta, newly_acked_sacked);
	}
	sndcnt = max(sndcnt, (fast_rexmit ? 1 : 0));
	tp->snd_cwnd = tcp_packets_in_flight(tp) + sndcnt;
}
```

Why it is not vulnerable: The division by tp->prior_cwnd in the delta < 0 branch (div_u64(dividend, tp->prior_cwnd)) is protected by an early return guard at the function entry: 'if (newly_acked_sacked <= 0 || WARN_ON_ONCE(!tp->prior_cwnd)) return;'. The short-circuit evaluation of the || operator ensures that if tp->prior_cwnd is zero, the function returns before reaching the division operation. This guard is evaluated before any code path that uses tp->prior_cwnd as a divisor.

Security invariants:
- tp->prior_cwnd must be non-zero before div_u64(dividend, tp->prior_cwnd) is reached. This is enforced by the guard 'if (newly_acked_sacked <= 0 || WARN_ON_ONCE(!tp->prior_cwnd)) return;' which uses short-circuit || evaluation, guaranteeing early return when tp->prior_cwnd is zero.
- The short-circuit evaluation of || ensures the WARN_ON_ONCE(!tp->prior_cwnd) check is always evaluated before any division by tp->prior_cwnd occurs, since the return statement immediately follows the guard.
- tcp_init_cwnd_reduction sets tp->prior_cwnd = tp->snd_cwnd, establishing that prior_cwnd reflects the congestion window value at the time congestion control state is initialized.

Invariant verification:
- Division by zero prevention for tp->prior_cwnd: holds=true. Evidence: The guard 'if (newly_acked_sacked <= 0 || WARN_ON_ONCE(!tp->prior_cwnd)) return;' at the function entry ensures tp->prior_cwnd != 0 before any subsequent code executes, including the div_u64(dividend, tp->prior_cwnd) call in the delta < 0 branch. The || operator's short-circuit semantics guarantee the check is evaluated and the return is taken if prior_cwnd is zero.
- All code paths reaching division pass the non-zero guard: holds=true. Evidence: The function has a single entry point and the guard is placed before all computational branches. The delta < 0 branch containing div_u64(dividend, tp->prior_cwnd) can only be reached after the guard has confirmed tp->prior_cwnd is non-zero.

Residual risk notes: The safety of the division relies on tp->prior_cwnd remaining non-zero between the guard check and the div_u64 call. If concurrent modification of tp->prior_cwnd were possible, a TOCTOU issue could arise. However, the surrounding TCP input processing context typically holds the socket lock (sk_lock), serializing access to these fields. Without visibility into the locking discipline in the callers, this assumption cannot be fully verified from the supplied context alone.

Based on the provided code and context, there are no discernible vulnerabilities in `tcp_cwnd_reduction`.

Here is an analysis of potential areas of concern and the guards that prevent them from being exploitable:

1. **Division by Zero:**
   The function calculates `div_u64(dividend, tp->prior_cwnd)`. A division by zero could cause a kernel panic. However, this is guarded at the beginning of the function:
   ```c
   if (newly_acked_sacked <= 0 || WARN_ON_ONCE(!tp->prior_cwnd))
       return;
   ```
   This ensures `tp->prior_cwnd` is strictly non-zero before reaching the division.

2. **Underflow / Type Conversion Issues in `delta`:**
   ```c
   int delta = tp->snd_ssthresh - tcp_packets_in_flight(tp);
   ```
   `tp->snd_ssthresh` and the return type of `tcp_packets_in_flight(tp)` are both unsigned 32-bit integers (`u32` / `unsigned int`). If packets in flight exceed the slow start threshold, the subtraction wraps around to a large `u32`. However, it is assigned to `int delta`. In C, this implicit two's complement conversion accurately converts the wrapped unsigned value into the correct negative signed integer. The subsequent `if (delta < 0)` check correctly identifies this state.

3. **Underflow in `max_t` arguments:**
   ```c
   max_t(int, tp->prr_delivered - tp->prr_out, newly_acked_sacked)
   ```
   `tp->prr_delivered` and `tp->prr_out` are `u32`. If `tp->prr_out > tp->prr_delivered`, their subtraction wraps to a large unsigned value. However, the `max_t` macro takes a cast type (here, `int`). Passing the wrapped unsigned expression into `max_t(int, ...)` safely casts it back to the corresponding negative signed integer before the comparison occurs, correctly evaluating it as less than `newly_acked_sacked` (which is strictly positive due to the early return guard).

4. **Negative Congestion Window Scaling:**
   `sndcnt` can be evaluated to a negative value during the PRR (Proportional Rate Reduction) calculations. This is safe because it is lower-bounded to `0` or `1` immediately afterward, ensuring the congestion window never steps backward improperly:
   ```c
   sndcnt = max(sndcnt, (fast_rexmit ? 1 : 0));
   tp->snd_cwnd = tcp_packets_in_flight(tp) + sndcnt;
   ```

**Verdict:** The function is robustly guarded against mathematical edge cases, relies correctly on two's complement mechanics for boundary logic, and appropriately bounds scaling factors. No vulnerability is present.

```json
{
  "vulnerable": false,
  "cwe": "N/A",
  "severity": "None",
  "reviewed_region": "tcp_cwnd_reduction",
  "vulnerable_region": "N/A",
  "root_cause": "N/A",
  "exploitability": "N/A",
  "attack_preconditions": "N/A",
  "impact": "N/A",
  "non_vulnerable_reason": "The function correctly handles mathematical edge cases, relying on standard two's complement mechanics for boundary logic. It effectively guards against division by zero and correctly bounds the scaling factors for the congestion window.",
  "security_invariants": "1. tp->prior_cwnd must be non-zero before being used as a divisor (enforced by early return on WARN_ON_ONCE(!tp->prior_cwnd)).\n2. sndcnt must not result in a negative congestion window adjustment (enforced by max(sndcnt, (fast_rexmit ? 1 : 0))).",
  "invariant_verification": "The zero check for tp->prior_cwnd happens before the division. The max() macro is applied to sndcnt before it is used to calculate tp->snd_cwnd, bounding it to at least 0 (or 1). Implicit casts to 'int' safely handle wrapped unsigned values for calculations like delta and max_t(...) arguments.",
  "residual_risk_notes": "None. The context provided sufficiently covers all variables and macros used in the calculations.",
  "call_path": "tcp_enter_cwr -> tcp_init_cwnd_reduction -> tcp_cwnd_reduction -> tcp_try_keep_open -> tcp_process_loss -> tcp_fastretrans_alert"
}
```

1. tp->prior_cwnd must be non-zero before being used as a divisor (enforced by early return on WARN_ON_ONCE(!tp->prior_cwnd)).
2. sndcnt must not result in a negative congestion window adjustment (enforced by max(sndcnt, (fast_rexmit ? 1 : 0))).


System:
You are a senior application security auditor reviewing code for potential vulnerabilities.

You will be given a candidate function, repository and file metadata, a reduced call path, and resolved cross-file context such as helper functions, structs, macros, constants, and related definitions. Use the supplied context actively, but stay strictly grounded in what is actually shown.

Work from the supplied code and surrounding context as the primary evidence. Do not assume a bug exists just because the sample was retrieved.

Analyze both control flow and data flow. Trace the relevant execution paths and track security-relevant data through inputs, transformations, conditions, helper calls, outputs, and side effects.

Reason about attacker influence, identify relevant guards or missing guards, and explain exploitability or non-exploitability before reaching a verdict.

When the code is vulnerable, explain the vulnerable behavior, root cause, realistic attack preconditions, likely impact, and the most precise vulnerability classification justified by the supplied code.

When the code is not vulnerable, explain the concrete invariants and guards that prevent the suspected issue, and note any residual uncertainty that remains from the supplied context.

Keep the analysis concrete and code-grounded. Separate observed evidence from inferred conclusion.

Audit the following candidate code to determine whether it presents a real vulnerability.
This sample may come from a noisy retrieval or transformation stage, so reason from the supplied code and context rather than assuming the label.

Repository: github.com/PrestaShop/productcomments
Language: PHP
File: productcomments.php
Function: renderAuthorName

Call path: renderAuthorName (productcomments.php)

### Primary Function

```php
public function renderAuthorName($value, $row)
{
    if (!empty($row['customer_id'])) {
        $linkToCustomerProfile = $this->context->link->getAdminLink('AdminCustomers', false, [], [
            'id_customer' => $row['customer_id'],
            'viewcustomer' => 1,
        ]);

        return '<a href="' . $linkToCustomerProfile . '">' . $value . '</a>';
    }

    return $value;
}
```

### Cross-File Context

[ProductComments — class — productcomments.php:34]
class ProductComments extends Module implements WidgetInterface

Provide the final verdict as strict JSON.

Return only one JSON object and no surrounding prose.

Return one JSON object with these keys:
- vulnerable
- cwe
- severity
- reviewed_region
- vulnerable_region
- root_cause
- exploitability
- attack_preconditions
- impact
- non_vulnerable_reason
- security_invariants
- invariant_verification
- residual_risk_notes
- call_path

Control flow: renderAuthorName is called as a callback by PrestaShop's AdminController grid rendering system. It receives a value (author name) and row data, then returns either a hyperlink to the customer profile with the author name embedded, or just the raw author name.

Data flow: The author name originates from user-submitted product comments (via $_POST when creating/editing comments), is stored in the database, and later retrieved and passed to renderAuthorName as the $value parameter without sanitization before being rendered into HTML.

Verdict: Vulnerable
Vulnerable region:
[productcomments.php]
```php
public function renderAuthorName($value, $row)
    {
        if (!empty($row['customer_id'])) {
            $linkToCustomerProfile = $this->context->link->getAdminLink('AdminCustomers', false, [], [
                'id_customer' => $row['customer_id'],
                'viewcustomer' => 1,
            ]);

            return '<a href="' . $linkToCustomerProfile . '">' . $value . '</a>';
        }

        return $value;
    }

    public function renderCriterionForm($id_criterion = 0)
    {
```
CWE: CWE-79
Severity: MEDIUM

Root cause: The renderAuthorName method directly concatenates the unescaped $value parameter into HTML anchor tags without applying any sanitization. The author name originates from user-submitted product reviews and is not sanitized before being rendered in the admin grid column.

Exploitability: An unauthenticated attacker can submit a product review with a malicious JavaScript payload in the author name field. The XSS will trigger when an administrator views the product comments admin grid, which calls renderAuthorName to display the author name.

Attack preconditions:
- Attacker can submit a product review with a crafted author name containing JavaScript
- Administrator views the product comments list in the PrestaShop admin panel
- No input validation sanitizes the author name before storage or rendering

Likely impact: An unauthenticated attacker can submit a product review with a malicious JavaScript payload in the author name field. The XSS will trigger when an administrator views the product comments admin grid, which calls renderAuthorName to display the author name.

public function renderAuthorName($value, $row)
    {
        if (!empty($row['customer_id'])) {
            $linkToCustomerProfile = $this->context->link->getAdminLink('AdminCustomers', false, [], [
                'id_customer' => $row['customer_id'],
                'viewcustomer' => 1,
            ]);

            return '' . $value . '';
        }

        return $value;
    }

    public function renderCriterionForm($id_criterion = 0)
    {

**Analysis:**

The function `renderAuthorName` is used as a callback to render the author's name in a list or grid (likely Prestashop's `HelperList` in the admin panel). It takes two arguments: `$value` (the author's name) and `$row` (the current data row).

When rendering the output, the function either wraps `$value` in an HTML `<a>` tag (if the comment is associated with a customer) or returns `$value` as-is. In Prestashop, if a column in a `HelperList` uses a callback, the framework assumes the callback might return HTML (which it does here, using the `<a>` tag) and outputs the returned string directly without escaping it.

Because `$value` is user-controlled data (the name of the person who submitted the product comment) and it is concatenated directly into the HTML string without being sanitized or escaped (e.g., using `htmlspecialchars()` or `escape()`), this introduces a Cross-Site Scripting (XSS) vulnerability.

**Root Cause:**
User-supplied input (`$value`) is included in the HTML output without proper output encoding.

**Exploitability and Impact:**
An attacker (such as an unauthenticated guest or an authenticated customer) can submit a product comment with a maliciously crafted author name (e.g., `<script>alert(1)</script>`). When a store administrator views the product comments list in the backend, the malicious payload will be executed within the context of the administrator's session. This Stored XSS can lead to session hijacking, privilege escalation, or unauthorized administrative actions.

**Vulnerability Classification:**
- CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

```json
{
  "vulnerable": true,
  "cwe": "CWE-79",
  "severity": "High",
  "reviewed_region": "public function renderAuthorName($value, $row)\n{\n    if (!empty($row['customer_id'])) {\n        $linkToCustomerProfile = $this->context->link->getAdminLink('AdminCustomers', false, [], [\n            'id_customer' => $row['customer_id'],\n            'viewcustomer' => 1,\n        ]);\n\n        return '<a href=\"' . $linkToCustomerProfile . '\">' . $value . '</a>';\n    }\n\n    return $value;\n}",
  "vulnerable_region": "return '<a href=\"' . $linkToCustomerProfile . '\">' . $value . '</a>';\n    }\n\n    return $value;",
  "root_cause": "The function returns user-controlled data (`$value`) embedded in HTML without applying HTML entity encoding (e.g., using `htmlspecialchars` or `Tools::safeOutput()`).",
  "exploitability": "Highly exploitable. An attacker can submit a product comment with an XSS payload in the author name field.",
  "attack_preconditions": "The attacker must be able to submit a product comment. Product comments must be enabled and viewable by an administrator.",
  "impact": "Stored Cross-Site Scripting (XSS) in the PrestaShop back office. When an administrator views the comments list, the payload executes in their browser, potentially allowing the attacker to hijack the admin session, perform administrative actions, or gain code execution.",
  "non_vulnerable_reason": "",
  "security_invariants": "",
  "invariant_verification": "",
  "residual_risk_notes": "",
  "call_path": "renderAuthorName (productcomments.php)"
}
```


Audit the following candidate code to determine whether it presents a real vulnerability.
This sample may come from a noisy retrieval or transformation stage, so reason from the supplied code and context rather than assuming the label.

Repository: https://github.com/torvalds/linux
Language: C
File: drivers/bluetooth/btusb.c
Function: btusb_mtk_claim_iso_intf

Call path: hci_power_on (net/bluetooth/hci_core.c) → hci_dev_open_sync (net/bluetooth/hci_sync.c) → btusb_mtk_setup (drivers/bluetooth/btusb.c) → btusb_mtk_claim_iso_intf (drivers/bluetooth/btusb.c) → usb_driver_claim_interface (drivers/usb/core/driver.c)

### Primary Function

```c
static void btusb_mtk_claim_iso_intf(struct btusb_data *data)
{
	struct btmtk_data *btmtk_data = hci_get_priv(data->hdev);
	int err;

	err = usb_driver_claim_interface(&btusb_driver,
					 btmtk_data->isopkt_intf, data);
	if (err < 0) {
		btmtk_data->isopkt_intf = NULL;
		bt_dev_err(data->hdev, "Failed to claim iso interface");
		return;
	}

	set_bit(BTMTK_ISOPKT_OVER_INTR, &btmtk_data->flags);
	init_usb_anchor(&btmtk_data->isopkt_anchor);
}
```

### Cross-File Context

[device_lock — function — include/linux/device.h]
```c
void device_lock(struct device *dev);
```

[device_unlock — function — include/linux/device.h]
```c
void device_unlock(struct device *dev);
```

[usb_driver_claim_interface — sink — include/linux/usb.h]
```c
int usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *intf, void *data);
```

[btmtk_data — struct — drivers/bluetooth/btmtk.h]
```c
struct btmtk_data {
	const char *drv_name;
	unsigned long flags;
	u32 dev_id;
	btmtk_reset_sync_func_t reset_sync;
	struct btmtk_coredump_info cd_info;
	struct usb_device *udev;
	struct usb_interface *intf;
	struct usb_anchor *ctrl_anchor;
	struct sk_buff *evt_skb;
	struct usb_endpoint_descriptor *isopkt_tx_ep;
	struct usb_endpoint_descriptor *isopkt_rx_ep;
	struct usb_interface *isopkt_intf;
	struct usb_anchor isopkt_anchor;
	struct sk_buff *isopkt_skb;
	spinlock_t isorxlock;
};
```

[MTK_ISO_IFNUM — constant — drivers/bluetooth/btmtk.h]
MTK_ISO_IFNUM → 2  (drivers/bluetooth/btmtk.h)

Control flow: When hci_power_on workqueue triggers, it calls hci_dev_open_sync which calls btusb_mtk_setup which calls btusb_mtk_claim_iso_intf. The vulnerable path calls usb_driver_claim_interface() without first acquiring the device lock. Concurrent USB suspend operations can access the interface structure simultaneously.

Data flow: btmtk_data->isopkt_intf (usb_interface pointer) is retrieved from hci_get_priv, then passed to usb_driver_claim_interface(). Without device_lock(), another thread can modify or clear this pointer leading to NULL dereference.

Verdict: Vulnerable
Vulnerable region:
[drivers/bluetooth/btusb.c]
```c
static void btusb_mtk_claim_iso_intf(struct btusb_data *data)
{
	struct btmtk_data *btmtk_data = hci_get_priv(data->hdev);
	int err;

	err = usb_driver_claim_interface(&btusb_driver,
					 btmtk_data->isopkt_intf, data);
	if (err < 0) {
		btmtk_data->isopkt_intf = NULL;
		bt_dev_err(data->hdev, "Failed to claim iso interface");
		return;
	}

	set_bit(BTMTK_ISOPKT_OVER_INTR, &btmtk_data->flags);
```
CWE: CWE-667
Severity: MEDIUM

Root cause: The btusb_mtk_claim_iso_intf function calls usb_driver_claim_interface() without holding the device lock (device_lock()) when called from the hci_power_on workqueue. The USB driver documentation states that the device lock must be held when calling usb_driver_claim_interface() from outside the probe routine. Without this lock, race conditions can occur leading to NULL pointer dereferences (intf->dev.driver being NULL) during suspend/resume operations.

Exploitability: The vulnerability is exploitable when MediaTek Bluetooth device attempts to power on via the hci_power_on workqueue path, causing concurrent access to USB interface device structures without proper locking

Attack preconditions:
- MediaTek Bluetooth USB device must be present
- Device power-on sequence must be triggered via hci_power_on workqueue
- USB suspend/resume or runtime suspend operations may trigger concurrently

Likely impact: The vulnerability is exploitable when MediaTek Bluetooth device attempts to power on via the hci_power_on workqueue path, causing concurrent access to USB interface device structures without proper locking

An analysis of the `btusb_mtk_claim_iso_intf` function and its call path reveals a concurrency vulnerability due to a missing device lock.

### Vulnerability Analysis

The function `btusb_mtk_claim_iso_intf` is called during the Bluetooth device setup phase (`hci_power_on` -> `hci_dev_open_sync` -> `btusb_mtk_setup`), which happens asynchronously well after the initial USB `probe` phase has completed.

In this function, `usb_driver_claim_interface()` is called to bind the `btusb_driver` to the `btmtk_data->isopkt_intf` interface. However, the USB core requires that if `usb_driver_claim_interface()` is called from anywhere other than a driver's `probe()` routine, the caller must hold the device lock (typically `device_lock(&intf->dev)` or similar, depending on the USB API requirements).

Because the `device_lock` is not acquired before making this call, the claiming of the interface can race with other USB core operations, such as a concurrent device disconnect (`usb_disconnect`) or an unbind via sysfs.

### Impact

If a malicious user or an unprivileged process triggers a concurrent unbind (e.g., via sysfs) or physical disconnect while the interface is being asynchronously claimed during `hci0 up`, it can lead to a Use-After-Free (UAF) or corruption of the driver core's internal data structures. This can result in a kernel panic (Denial of Service) or potentially local privilege escalation depending on how the freed interface memory is reallocated.

### Conclusion
The code is vulnerable to a race condition/Use-After-Free due to a missing device lock when claiming the USB interface outside of the initialization/probe context.

To fix this, the interface device lock should be explicitly acquired and released:
```c
/* Pseudocode */
device_lock(&btmtk_data->isopkt_intf->dev);
err = usb_driver_claim_interface(&btusb_driver, btmtk_data->isopkt_intf, data);
device_unlock(&btmtk_data->isopkt_intf->dev);
```

```json
{
  "vulnerable": true,
  "cwe": "CWE-362",
  "severity": "Medium",
  "reviewed_region": "static void btusb_mtk_claim_iso_intf(struct btusb_data *data)\n{\n\tstruct btmtk_data *btmtk_data = hci_get_priv(data->hdev);\n\tint err;\n\n\terr = usb_driver_claim_interface(&btusb_driver,\n\t\t\t\t\t btmtk_data->isopkt_intf, data);\n\tif (err < 0) {\n\t\tbtmtk_data->isopkt_intf = NULL;\n\t\tbt_dev_err(data->hdev, \"Failed to claim iso interface\");\n\t\treturn;\n\t}\n\n\tset_bit(BTMTK_ISOPKT_OVER_INTR, &btmtk_data->flags);\n\tinit_usb_anchor(&btmtk_data->isopkt_anchor);\n}",
  "vulnerable_region": "\terr = usb_driver_claim_interface(&btusb_driver,\n\t\t\t\t\t btmtk_data->isopkt_intf, data);",
  "root_cause": "The function calls usb_driver_claim_interface() outside of the driver's probe() context without holding the device lock for the interface.",
  "exploitability": "An attacker with local access (e.g., able to trigger USB device unbind via sysfs) or physical access (unplugging the device) can trigger a race condition against an asynchronous Bluetooth power-on sequence.",
  "attack_preconditions": "The device must be present and the attacker must be able to trigger a device unbind/disconnect concurrently with the Bluetooth interface being brought up (e.g., via `hciconfig hci0 up`).",
  "impact": "Race condition leading to a Use-After-Free (UAF) of driver/USB core structures, which can cause kernel panics (Denial of Service) and potentially local privilege escalation.",
  "non_vulnerable_reason": "",
  "security_invariants": [],
  "invariant_verification": [],
  "residual_risk_notes": "",
  "call_path": [
    "hci_power_on",
    "hci_dev_open_sync",
    "btusb_mtk_setup",
    "btusb_mtk_claim_iso_intf"
  ]
}
```


Audit the following candidate code to determine whether it presents a real vulnerability.
This sample may come from a noisy retrieval or transformation stage, so reason from the supplied code and context rather than assuming the label.

Repository: github.com/dogtagpki/jss.git
Language: Java
File: src/main/java/org/mozilla/jss/ssl/javax/JSSEngineReferenceImpl.java
Function: checkSSLAlerts

Call path: JSSEngineReferenceImpl.wrap/unwrap (src/main/java/org/mozilla/jss/ssl/javax/JSSEngineReferenceImpl.java) → checkSSLAlerts (src/main/java/org/mozilla/jss/ssl/javax/JSSEngineReferenceImpl.java) → SSLAlertEvent.setEngine (src/main/java/org/mozilla/jss/ssl/SSLAlertEvent.java)

### Primary Function

```java
private SSLException checkSSLAlerts() {
        debug("JSSEngine: Checking inbound and outbound SSL Alerts. Have " + ssl_fd.inboundAlerts.size() + " inbound and " + ssl_fd.outboundAlerts.size() + " outbound alerts.");

        // Prefer inbound alerts to outbound alerts.
        while (ssl_fd.inboundOffset < ssl_fd.inboundAlerts.size()) {
            SSLAlertEvent event = ssl_fd.inboundAlerts.get(ssl_fd.inboundOffset);
            ssl_fd.inboundOffset += 1;

            if (event.getLevelEnum() == SSLAlertLevel.WARNING && event.getDescriptionEnum() == SSLAlertDescription.CLOSE_NOTIFY) {
                debug("Got inbound CLOSE_NOTIFY alert");
                closeInbound();
            }

            debug("JSSEngine: Got inbound alert: " + event);

            // Fire inbound alert prior to raising any exception.
            fireAlertReceived(event);

            // Not every SSL Alert is fatal; toException() only returns a
            // SSLException on fatal instances. We shouldn't return NULL
            // early without checking all alerts.
            SSLException exception = event.toException();
            if (exception != null) {
                return exception;
            }
        }

        while (ssl_fd.outboundOffset < ssl_fd.outboundAlerts.size()) {
            SSLAlertEvent event = ssl_fd.outboundAlerts.get(ssl_fd.outboundOffset);
            ssl_fd.outboundOffset += 1;

            if (event.getLevelEnum() == SSLAlertLevel.WARNING && event.getDescriptionEnum() == SSLAlertDescription.CLOSE_NOTIFY) {
                debug("Sent outbound CLOSE_NOTIFY alert.");
                closeOutbound();
            }

            debug("JSSEngine: Got outbound alert: " + event);

            // Fire outbound alert prior to raising any exception. Note that
            // this still triggers after this alert is written to the output
            // wire buffer.
            fireAlertSent(event);

            SSLException exception = event.toException();
            if (exception != null) {
                return exception;
            }
        }

        return null;
    }
```

### Cross-File Context

[JSSEngineReferenceImpl — class — src/main/java/org/mozilla/jss/ssl/javax/JSSEngineReferenceImpl.java]
public class JSSEngineReferenceImpl extends JSSEngine

[SSLAlertEvent — class — src/main/java/org/mozilla/jss/ssl/SSLAlertEvent.java]
public class SSLAlertEvent extends EventObject { private static final long serialVersionUID = 1L; int level; int description; transient JSSEngine engine; SSLAlertLevel levelEnum; SSLAlertDescription descriptionEnum; public SSLAlertEvent(SSLSocket socket) { super(socket); } public SSLAlertEvent(SSLSocket socket, int level, int description) { super(socket); setLevel(level); setDescription(description); } public SSLAlertEvent(SSLSocket socket, SSLAlertLevel level, SSLAlertDescription description) { super(socket); setLevel(level); setDescription(description); } public SSLAlertEvent(SSLFDProxy proxy) { super(proxy); } public SSLAlertEvent(SSLFDProxy proxy, int level, int description) { super(proxy); setLevel(level); setDescription(description); } public SSLAlertEvent(SSLFDProxy proxy, SSLAlertLevel level, SSLAlertDescription description) { super(proxy); setLevel(level); setDescription(description); } public SSLSocket getSocket() { Object obj = getSource(); return obj instanceof SSLSocket ? (SSLSocket) obj : null; } public SSLFDProxy getFileDesc() { Object obj = getSource(); return obj instanceof SSLFDProxy ? (SSLFDProxy) obj : null; } public int getLevel() { return level; } public SSLAlertLevel getLevelEnum() { return levelEnum; } public void setLevel(int level) { this.level = level; this.levelEnum = SSLAlertLevel.valueOf(level); } public void setLevel(SSLAlertLevel level) { this.levelEnum = level; this.level = level.getID(); } public int getDescription() { return description; } public SSLAlertDescription getDescriptionEnum() { return descriptionEnum; } public void setDescription(int description) { this.description = description; this.descriptionEnum = SSLAlertDescription.valueOf(description); } public void setDescription(SSLAlertDescription description) { this.descriptionEnum = description; this.description = description.getID(); } public JSSEngine getEngine() { return engine; } public void setEngine(JSSEngine new_engine) { engine = new_engine; } public SSLException toException() { if (levelEnum == SSLAlertLevel.FATAL) { Class<? extends SSLException> exception_class = descriptionEnum.getExceptionClass(); SSLException exception; try { exception = exception_class.getConstructor(String.class).newInstance(this.toString()); } catch (Exception e) { exception = new SSLException(this.toString()); } return exception; } return null; } public void throwException() throws SSLException { throw this.toException(); } @Override public String toString() { return this.levelEnum + ": " + this.descriptionEnum; } }

[SSLFDProxy — class — src/main/java/org/mozilla/jss/nss/SSLFDProxy.java]
public class SSLFDProxy extends PRFDProxy { public PK11Cert clientCert; public GlobalRefProxy globalRef; public ArrayList<SSLAlertEvent> inboundAlerts; public int inboundOffset; public ArrayList<SSLAlertEvent> outboundAlerts; public int outboundOffset; public boolean needCertValidation; public boolean needBadCertValidation; public int badCertError; public boolean handshakeComplete; public CertAuthHandler certAuthHandler; public BadCertHandler badCertHandler; public SSLFDProxy(byte[] pointer) { super(pointer); globalRef = new GlobalRefProxy(this); } public void SetClientCert(X509Certificate cert) throws IllegalArgumentException { if (!(cert instanceof PK11Cert)) { throw new IllegalArgumentException("Unable to cast given certificate to PK11Cert: " + cert.getClass().getName()); } clientCert = (PK11Cert)cert; } @Override protected synchronized void releaseNativeResources() throws Exception { super.releaseNativeResources(); if (globalRef != null) { try { globalRef.close(); } finally { globalRef = null; } } } public int invokeCertAuthHandler() { return certAuthHandler.check(this); } public int invokeBadCertHandler(int error) { return badCertHandler.check(this, error); } }

[cleanup — method — src/main/java/org/mozilla/jss/ssl/javax/JSSEngineReferenceImpl.java]
@Override protected void finalize() { cleanup(); }

Control flow: The checkSSLAlerts method iterates through two lists of SSLAlertEvent objects: inboundAlerts and outboundAlerts, using offset counters (inboundOffset/outboundOffset) to track processing position. For each event, it checks if it's a CLOSE_NOTIFY alert and calls closeInbound()/closeOutbound() respectively, fires alert events via fireAlertReceived()/fireAlertSent(), and calls toException() to check for fatal errors. If a fatal exception is found, it returns immediately. Otherwise, after processing all alerts, it returns null. The method is called from wrap/unwrap operations.

Data flow: SSLAlertEvent objects are retrieved from ssl_fd.inboundAlerts and ssl_fd.outboundAlerts ArrayLists. Each event has a level and description that determine whether it's fatal. The events are passed to fireAlertReceived/fireAlertSent callbacks and toException() for exception generation. According to the call path, SSLAlertEvent.setEngine is invoked, which sets the transient JSSEngine engine field in the event, creating a back-reference from the alert event to the engine instance.

Verdict: Not Vulnerable

Reviewed region:
[src/main/java/org/mozilla/jss/ssl/javax/JSSEngineReferenceImpl.java]
```java
private SSLException checkSSLAlerts() {
        debug("JSSEngine: Checking inbound and outbound SSL Alerts. Have " + ssl_fd.inboundAlerts.size() + " inbound and " + ssl_fd.outboundAlerts.size() + " outbound alerts.");

        // Prefer inbound alerts to outbound alerts.
        while (ssl_fd.inboundOffset < ssl_fd.inboundAlerts.size()) {
            SSLAlertEvent event = ssl_fd.inboundAlerts.get(ssl_fd.inboundOffset);
            ssl_fd.inboundOffset += 1;

            if (event.getLevelEnum() == SSLAlertLevel.WARNING && event.getDescriptionEnum() == SSLAlertDescription.CLOSE_NOTIFY) {
                debug("Got inbound CLOSE_NOTIFY alert");
                closeInbound();
            }

            debug("JSSEngine: Got inbound alert: " + event);

            // Fire inbound alert prior to raising any exception.
            fireAlertReceived(event);

            // Not every SSL Alert is fatal; toException() only returns a
            // SSLException on fatal instances. We shouldn't return NULL
            // early without checking all alerts.
            SSLException exception = event.toException();
            if (exception != null) {
                return exception;
            }
        }

        while (ssl_fd.outboundOffset < ssl_fd.outboundAlerts.size()) {
            SSLAlertEvent event = ssl_fd.outboundAlerts.get(ssl_fd.outboundOffset);
            ssl_fd.outboundOffset += 1;

            if (event.getLevelEnum() == SSLAlertLevel.WARNING && event.getDescriptionEnum() == SSLAlertDescription.CLOSE_NOTIFY) {
                debug("Sent outbound CLOSE_NOTIFY alert.");
                closeOutbound();
            }

            debug("JSSEngine: Got outbound alert: " + event);

            // Fire outbound alert prior to raising any exception. Note that
            // this still triggers after this alert is written to the output
            // wire buffer.
            fireAlertSent(event);

            SSLException exception = event.toException();
            if (exception != null) {
                return exception;
            }
        }

        return null;
    }
```

Why it is not vulnerable: The SSLAlertEvent class uses a 'transient' field for the JSSEngine reference ('transient JSSEngine engine'), and the alerts are processed through offset-based iteration (inboundOffset/outboundOffset) that advances through the lists. The offset counters serve as a processing cursor rather than an accumulating collection. The SSLAlertEvent instances in the inboundAlerts/outboundAlerts lists are processed and the offset advances past them, meaning processed events are not actively referenced after iteration past them. The cycle would be: JSSEngineReferenceImpl -> ssl_fd (SSLFDProxy) -> ArrayList<SSLAlertEvent> -> SSLAlertEvent -> engine field -> JSSEngineReferenceImpl. However, since alerts are processed via offset advancement and the lists are bounded by the number of alerts received (not accumulating indefinitely from this method's perspective), and processed alerts beyond the offset would be eligible for garbage collection once the offset moves past them, this does not constitute a concrete resource leak vulnerability in the current code.

Security invariants:
- Alert processing uses offset counters (inboundOffset, outboundOffset) to track which alerts have been processed, preventing re-processing and allowing the offset to advance past processed events
- The SSLAlertEvent engine field is declared as 'transient JSSEngine engine', indicating it is not part of persistent storage and is a lightweight back-reference
- Alert lists (inboundAlerts, outboundAlerts) are ArrayList instances bounded by alerts received from the SSL layer, not unbounded accumulation
- The fireAlertReceived/fireAlertSent callbacks receive the event but the current code does not show persistent storage of these events beyond the existing lists

Invariant verification:
- Offset-based iteration prevents unbounded event accumulation in active processing: holds=true. Evidence: ssl_fd.inboundOffset += 1 and ssl_fd.outboundOffset += 1 advance past processed events; while loops check 'ssl_fd.inboundOffset < ssl_fd.inboundAlerts.size()'
- Engine reference in events is transient: holds=true. Evidence: SSLAlertEvent declares 'transient JSSEngine engine' and provides 'setEngine(JSSEngine new_engine)' to assign it
- Alert lists are standard ArrayList instances without custom retention semantics: holds=true. Evidence: SSLFDProxy declares 'public ArrayList<SSLAlertEvent> inboundAlerts' and 'public ArrayList<SSLAlertEvent> outboundAlerts'

Residual risk notes: The actual management of alert list lifecycle (creation, clearing, resizing) is not visible in the supplied code. If the inboundAlerts/outboundAlerts lists grow without bound and are never cleared, or if fireAlertReceived/fireAlertSent (not shown) retain references to events beyond processing, that could create retention issues. The setEngine call referenced in the call path is not directly visible in checkSSLAlerts - it likely occurs within fireAlertReceived/fireAlertSent. Without seeing those methods, we cannot fully verify whether event references are released after processing.

No concrete vulnerability impact is demonstrated in the supplied code and context.

**Verdict:** Vulnerable

**Vulnerability:** Memory Leak / Unbounded Resource Consumption (Denial of Service)

**Root Cause:**
In `checkSSLAlerts`, the application processes inbound and outbound SSL alerts by reading from `ssl_fd.inboundAlerts` and `ssl_fd.outboundAlerts`. Instead of removing the processed events from the lists or periodically clearing the lists, the code merely increments the `inboundOffset` and `outboundOffset` variables:
```java
SSLAlertEvent event = ssl_fd.inboundAlerts.get(ssl_fd.inboundOffset);
ssl_fd.inboundOffset += 1;
```
Because the underlying `ArrayList` instances retain references to all historical `SSLAlertEvent` objects, they will grow indefinitely over the lifetime of the connection.

**Attack Preconditions:**
An attacker must be able to establish a TLS connection with the application and repeatedly send non-fatal `WARNING` alerts (e.g., `no_renegotiation` or `user_canceled` alerts). Because non-fatal alerts do not necessarily terminate the connection, the attacker can keep the connection open and continuously spam alerts.

**Impact:**
A sustained stream of warning alerts will force the `ArrayList` to grow without bound until the Java Virtual Machine runs out of heap memory. This leads to an `OutOfMemoryError` and crashes the application, resulting in a Denial of Service (DoS).

```json
{
  "vulnerable": true,
  "cwe": "CWE-400",
  "severity": "Medium",
  "reviewed_region": "private SSLException checkSSLAlerts() {\n        debug(\"JSSEngine: Checking inbound and outbound SSL Alerts. Have \" + ssl_fd.inboundAlerts.size() + \" inbound and \" + ssl_fd.outboundAlerts.size() + \" outbound alerts.\");\n\n        // Prefer inbound alerts to outbound alerts.\n        while (ssl_fd.inboundOffset < ssl_fd.inboundAlerts.size()) {\n            SSLAlertEvent event = ssl_fd.inboundAlerts.get(ssl_fd.inboundOffset);\n            ssl_fd.inboundOffset += 1;\n\n            if (event.getLevelEnum() == SSLAlertLevel.WARNING && event.getDescriptionEnum() == SSLAlertDescription.CLOSE_NOTIFY) {\n                debug(\"Got inbound CLOSE_NOTIFY alert\");\n                closeInbound();\n            }\n\n            debug(\"JSSEngine: Got inbound alert: \" + event);\n\n            // Fire inbound alert prior to raising any exception.\n            fireAlertReceived(event);\n\n            // Not every SSL Alert is fatal; toException() only returns a\n            // SSLException on fatal instances. We shouldn't return NULL\n            // early without checking all alerts.\n            SSLException exception = event.toException();\n            if (exception != null) {\n                return exception;\n            }\n        }\n\n        while (ssl_fd.outboundOffset < ssl_fd.outboundAlerts.size()) {\n            SSLAlertEvent event = ssl_fd.outboundAlerts.get(ssl_fd.outboundOffset);\n            ssl_fd.outboundOffset += 1;\n\n            if (event.getLevelEnum() == SSLAlertLevel.WARNING && event.getDescriptionEnum() == SSLAlertDescription.CLOSE_NOTIFY) {\n                debug(\"Sent outbound CLOSE_NOTIFY alert.\");\n                closeOutbound();\n            }\n\n            debug(\"JSSEngine: Got outbound alert: \" + event);\n\n            // Fire outbound alert prior to raising any exception. Note that\n            // this still triggers after this alert is written to the output\n            // wire buffer.\n            fireAlertSent(event);\n\n            SSLException exception = event.toException();\n            if (exception != null) {\n                return exception;\n            }\n        }\n\n        return null;\n    }",
  "vulnerable_region": "        while (ssl_fd.inboundOffset < ssl_fd.inboundAlerts.size()) {\n            SSLAlertEvent event = ssl_fd.inboundAlerts.get(ssl_fd.inboundOffset);\n            ssl_fd.inboundOffset += 1;\n...\n        while (ssl_fd.outboundOffset < ssl_fd.outboundAlerts.size()) {\n            SSLAlertEvent event = ssl_fd.outboundAlerts.get(ssl_fd.outboundOffset);\n            ssl_fd.outboundOffset += 1;",
  "root_cause": "The code processes SSL alerts from ArrayLists (`inboundAlerts` and `outboundAlerts`) by merely incrementing offset variables without ever removing the processed elements. Since non-fatal alerts do not necessarily cause the connection to terminate, the ArrayLists can grow indefinitely.",
  "exploitability": "An attacker can keep an SSL connection open and continuously send non-fatal warning alerts. Because the alerts are stored in ArrayLists and only skipped via an offset index instead of being removed, memory usage will continually grow.",
  "attack_preconditions": "The attacker needs to establish an SSL connection and continuously send non-fatal SSL alert messages without dropping the connection.",
  "impact": "Sustained alert spamming will exhaust JVM heap memory, eventually throwing an OutOfMemoryError and crashing the application (Denial of Service).",
  "non_vulnerable_reason": "",
  "security_invariants": "",
  "invariant_verification": "",
  "residual_risk_notes": "",
  "call_path": "JSSEngineReferenceImpl.wrap/unwrap (src/main/java/org/mozilla/jss/ssl/javax/JSSEngineReferenceImpl.java) \u2192 checkSSLAlerts (src/main/java/org/mozilla/jss/ssl/javax/JSSEngineReferenceImpl.java) \u2192 SSLAlertEvent.setEngine (src/main/java/org/mozilla/jss/ssl/SSLAlertEvent.java)"
}
```

        while (ssl_fd.inboundOffset < ssl_fd.inboundAlerts.size()) {
            SSLAlertEvent event = ssl_fd.inboundAlerts.get(ssl_fd.inboundOffset);
            ssl_fd.inboundOffset += 1;
...
        while (ssl_fd.outboundOffset < ssl_fd.outboundAlerts.size()) {
            SSLAlertEvent event = ssl_fd.outboundAlerts.get(ssl_fd.outboundOffset);
            ssl_fd.outboundOffset += 1;


Audit the following candidate code to determine whether it presents a real vulnerability.
This sample may come from a noisy retrieval or transformation stage, so reason from the supplied code and context rather than assuming the label.

Repository: git.kernel.org/pub/scm/linux/kernel/git/stable/linux
Language: C
File: net/wireless/nl80211.c
Function: nl80211_set_wiphy

Call path: nl80211_set_wiphy (net/wireless/nl80211.c) → nla_get_u32 (lib/nlattr.c) → rdev_set_wiphy_params (net/wireless/rdev-ops.h) → fq_tin_dequeue (include/net/fq_impl.h)

### Primary Function

```c
static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = NULL;
	struct net_device *netdev = NULL;
	struct wireless_dev *wdev;
	int result = 0, rem_txq_params = 0;
	struct nlattr *nl_txq_params;
	u32 changed;
	u8 retry_short = 0, retry_long = 0;
	u32 frag_threshold = 0, rts_threshold = 0;
	u8 coverage_class = 0;
	u32 txq_limit = 0, txq_memory_limit = 0, txq_quantum = 0;

	rtnl_lock();
	/* ... wiphy/device lookup ... */

	wiphy_lock(&rdev->wiphy);

	/* ... various attribute handling ... */

	if (info->attrs[NL80211_ATTR_TXQ_QUANTUM]) {
		if (!wiphy_ext_feature_isset(&rdev->wiphy,
					     NL80211_EXT_FEATURE_TXQS)) {
			result = -EOPNOTSUPP;
			goto out;
		}
		txq_quantum = nla_get_u32(
			info->attrs[NL80211_ATTR_TXQ_QUANTUM]);
		changed |= WIPHY_PARAM_TXQ_QUANTUM;
	}

	if (changed) {
		/* ... old value backup ... */
		if (changed & WIPHY_PARAM_TXQ_QUANTUM)
			rdev->wiphy.txq_quantum = txq_quantum;

		result = rdev_set_wiphy_params(rdev, changed);
		if (result) {
			/* ... restore old values ... */
			goto out;
		}
	}

	result = 0;

out:
	wiphy_unlock(&rdev->wiphy);
	return result;
}
```

### Cross-File Context

[q_range — struct — net/wireless/nl80211.c:466-468]
```c
static struct netlink_range_validation q_range = {
	.max = INT_MAX,
};
```

[nl80211_policy — struct — net/wireless/nl80211.c:470-752]
```c
static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
	/* ... many entries ... */
	[NL80211_ATTR_TXQ_QUANTUM] = { .type = NLA_U32 }, /* pre-fix */
	[NL80211_ATTR_TXQ_QUANTUM] = NLA_POLICY_FULL_RANGE(NLA_U32, &q_range), /* post-fix */
	/* ... many entries ... */
};
```

[NL80211_ATTR_TXQ_QUANTUM — constant — include/uapi/linux/nl80211.h]
NL80211_ATTR_TXQ_QUANTUM → 323  (include/uapi/linux/nl80211.h)

[NLA_POLICY_FULL_RANGE — macro — include/net/netlink.h]
NLA_POLICY_FULL_RANGE → #define NLA_POLICY_FULL_RANGE(type, range) \ NLA_POLICY_RANGE(type, (range)->min, (range)->max)  (include/net/netlink.h)

Control flow: The function nl80211_set_wiphy begins by acquiring rtnl_lock() and performing wiphy/device lookup. It then acquires wiphy_lock(&rdev->wiphy) before processing netlink attributes. For the TXQ_QUANTUM attribute, it first checks if the NL80211_EXT_FEATURE_TXQS extension feature is enabled; if not, it sets result to -EOPNOTSUPP and jumps to the out label. If the feature is present, it extracts the u32 value via nla_get_u32() and marks WIPHY_PARAM_TXQ_QUANTUM as changed. When changed flags are set, old values are backed up, rdev->wiphy.txq_quantum is updated, and rdev_set_wiphy_params() is called. On error from rdev_set_wiphy_params(), old values are restored before jumping to out. The out label releases wiphy_unlock(&rdev->wiphy) and returns the result.

Data flow: User-supplied input arrives via info->attrs[NL80211_ATTR_TXQ_QUANTUM] from a netlink message. The nl80211_policy array governs validation during netlink parsing: the entry for NL80211_ATTR_TXQ_QUANTUM uses NLA_POLICY_FULL_RANGE(NLA_U32, &q_range), which constrains the value against the q_range structure (with max = INT_MAX). After validation, nla_get_u32() extracts the bounded value into the local variable txq_quantum. This value is conditionally stored into rdev->wiphy.txq_quantum and passed through rdev_set_wiphy_params(rdev, changed). The call path eventually reaches fq_tin_dequeue via rdev-ops.h.

Verdict: Not Vulnerable

Reviewed region:
[net/wireless/nl80211.c]
```c
static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = NULL;
	struct net_device *netdev = NULL;
	struct wireless_dev *wdev;
	int result = 0, rem_txq_params = 0;
	struct nlattr *nl_txq_params;
	u32 changed;
	u8 retry_short = 0, retry_long = 0;
	u32 frag_threshold = 0, rts_threshold = 0;
	u8 coverage_class = 0;
	u32 txq_limit = 0, txq_memory_limit = 0, txq_quantum = 0;

	rtnl_lock();
	/* ... wiphy/device lookup ... */

	wiphy_lock(&rdev->wiphy);

	/* ... various attribute handling ... */

	if (info->attrs[NL80211_ATTR_TXQ_QUANTUM]) {
		if (!wiphy_ext_feature_isset(&rdev->wiphy,
					     NL80211_EXT_FEATURE_TXQS)) {
			result = -EOPNOTSUPP;
			goto out;
		}
		txq_quantum = nla_get_u32(
			info->attrs[NL80211_ATTR_TXQ_QUANTUM]);
		changed |= WIPHY_PARAM_TXQ_QUANTUM;
	}

	if (changed) {
		/* ... old value backup ... */
		if (changed & WIPHY_PARAM_TXQ_QUANTUM)
			rdev->wiphy.txq_quantum = txq_quantum;

		result = rdev_set_wiphy_params(rdev, changed);
		if (result) {
			/* ... restore old values ... */
			goto out;
		}
	}

	result = 0;

out:
	wiphy_unlock(&rdev->wiphy);
	return result;
}
```

Why it is not vulnerable: The user-supplied txq_quantum value is validated by the netlink policy infrastructure before it is processed. The nl80211_policy entry for NL80211_ATTR_TXQ_QUANTUM specifies NLA_POLICY_FULL_RANGE(NLA_U32, &q_range), which bounds the accepted value against q_range.max (INT_MAX). This prevents unbounded user-controlled values from being accepted. Additionally, the code checks wiphy_ext_feature_isset(&rdev->wiphy, NL80211_EXT_FEATURE_TXQS) before processing the attribute, rejecting it with -EOPNOTSUPP if the hardware/driver does not support TXQs. The value is then stored into rdev->wiphy.txq_quantum and passed to rdev_set_wiphy_params under proper locking (wiphy_lock), ensuring consistent access.

Security invariants:
- The txq_quantum input must be validated against a defined maximum range before use — enforced by nl80211_policy[NL80211_ATTR_TXQ_QUANTUM] = NLA_POLICY_FULL_RANGE(NLA_U32, &q_range) with q_range.max = INT_MAX
- The txq_quantum attribute must only be processed when the device supports TXQ features — enforced by the wiphy_ext_feature_isset(&rdev->wiphy, NL80211_EXT_FEATURE_TXQS) check that returns -EOPNOTSUPP if the feature is absent
- Modifications to wiphy parameters must occur under proper serialization — enforced by wiphy_lock(&rdev->wiphy) acquired before reading/writing rdev->wiphy.txq_quantum and calling rdev_set_wiphy_params, with wiphy_unlock at the out label
- On failure of rdev_set_wiphy_params, previously modified values must be restored — enforced by the error path that backs up old values before modification and restores them in the error branch before jumping to out
- The rtnl_lock must be held during device lookup and parameter setting — enforced by rtnl_lock() at the start of the function

Invariant verification:
- Range validation of NL80211_ATTR_TXQ_QUANTUM against defined maximum: holds=true. Evidence: nl80211_policy[NL80211_ATTR_TXQ_QUANTUM] = NLA_POLICY_FULL_RANGE(NLA_U32, &q_range) expands to NLA_POLICY_RANGE(NLA_U32, q_range.min, q_range.max) with q_range.max = INT_MAX, ensuring the netlink parser rejects values exceeding this bound
- Feature capability check before processing txq_quantum: holds=true. Evidence: The guard if (!wiphy_ext_feature_isset(&rdev->wiphy, NL80211_EXT_FEATURE_TXQS)) { result = -EOPNOTSUPP; goto out; } prevents processing when the driver does not support TXQs
- Mutual exclusion during wiphy parameter modification: holds=true. Evidence: wiphy_lock(&rdev->wiphy) is acquired before the attribute processing section, and wiphy_unlock(&rdev->wiphy) is called at the out label on all exit paths
- Atomicity of parameter changes with rollback on error: holds=true. Evidence: Old values are backed up before modification, and the error path after rdev_set_wiphy_params failure includes restoration logic before goto out

Residual risk notes: The range validation caps txq_quantum at INT_MAX (2^31 - 1), which is a large value. Whether this upper bound is sufficient to prevent excessive resource allocation or loop iteration in downstream code (rdev_set_wiphy_params and fq_tin_dequeue) depends on the semantics of how txq_quantum is consumed; the current context does not expose those callees' internal behavior. Additionally, the interaction between the netlink policy validation and nla_get_u32() relies on the netlink infrastructure correctly applying the policy before get functions are called.

An analysis of the supplied code and context reveals a vulnerability related to missing bounds checking on a netlink attribute, which can lead to integer overflow and Denial of Service (DoS) in the kernel's fair queueing logic.

### Vulnerability Explanation
In `nl80211_set_wiphy`, the `NL80211_ATTR_TXQ_QUANTUM` attribute is parsed directly as an unsigned 32-bit integer (`NLA_U32`) without any range restrictions in the pre-fix netlink policy:
```c
txq_quantum = nla_get_u32(info->attrs[NL80211_ATTR_TXQ_QUANTUM]);
```
This value is subsequently saved into `rdev->wiphy.txq_quantum` and propagated to the underlying driver/mac80211 queueing components. The provided call path shows this value ultimately reaching the fairness queueing dequeue logic (`fq_tin_dequeue` in `include/net/fq_impl.h`).

In fair queueing algorithms (like FQ or FQ-CoDel), the "quantum" is added to a flow's "deficit" (which tracks how many bytes a flow is allowed to send). Deficit tracking logic relies on bounded quantum values and typically uses signed integers. If an attacker supplies a large `u32` value (e.g., `UINT_MAX` or greater than `INT_MAX`), adding this quantum to the deficit variable causes an integer overflow. This can result in the deficit becoming negative or unexpectedly wrapping around, which disrupts the queueing algorithm's invariants and often leads to infinite loops in the dequeue process.

### Preconditions and Exploitability
1. **Privileges**: Triggering this path requires the attacker to have the `CAP_NET_ADMIN` capability (or be in a user namespace that grants it), as modifying `wiphy` parameters is a privileged administrative operation.
2. **Device Features**: The wireless device must support the `NL80211_EXT_FEATURE_TXQS` feature.

While this requires administrative privileges, the ability to trivially trigger a kernel infinite loop or panic constitutes a local Denial of Service (DoS).

### Root Cause
The root cause is a missing validation bound for the `NL80211_ATTR_TXQ_QUANTUM` netlink attribute in `nl80211_policy`. It permitted the full range of a 32-bit unsigned integer, whereas the underlying fair queueing logic cannot safely handle quanta greater than `INT_MAX` (2147483647).

As shown in the supplied context, the fix explicitly restricts the netlink policy to bound the maximum value to `INT_MAX`:
```c
static struct netlink_range_validation q_range = {
	.max = INT_MAX,
};
[NL80211_ATTR_TXQ_QUANTUM] = NLA_POLICY_FULL_RANGE(NLA_U32, &q_range),
```

### Vulnerability Classification
- **CWE-190**: Integer Overflow or Wraparound
- **CWE-20**: Improper Input Validation

```json
{
  "vulnerable": true,
  "cwe": [
    "CWE-190",
    "CWE-20"
  ],
  "severity": "Medium",
  "reviewed_region": "net/wireless/nl80211.c",
  "vulnerable_region": "nl80211_set_wiphy",
  "root_cause": "Missing bounds checking for the NL80211_ATTR_TXQ_QUANTUM attribute. The original netlink policy allowed any u32 value, which can exceed INT_MAX and cause integer overflows in downstream fair queueing calculations (fq_tin_dequeue).",
  "exploitability": "An attacker with CAP_NET_ADMIN can send a malicious netlink message to set the txq_quantum parameter to a value greater than INT_MAX. This propagates to the FQ deficit calculation.",
  "attack_preconditions": "The attacker must have CAP_NET_ADMIN capability, and the target wireless device must have the NL80211_EXT_FEATURE_TXQS feature set.",
  "impact": "Denial of Service (DoS) due to kernel infinite loop or panic when the fairness queueing deficit variables overflow.",
  "non_vulnerable_reason": null,
  "security_invariants": null,
  "invariant_verification": null,
  "residual_risk_notes": null,
  "call_path": [
    "nl80211_set_wiphy (net/wireless/nl80211.c)",
    "nla_get_u32 (lib/nlattr.c)",
    "rdev_set_wiphy_params (net/wireless/rdev-ops.h)",
    "fq_tin_dequeue (include/net/fq_impl.h)"
  ]
}
```


Audit the following candidate code to determine whether it presents a real vulnerability.
This sample may come from a noisy retrieval or transformation stage, so reason from the supplied code and context rather than assuming the label.

Repository: github.com/apache/mynewt-nimble
Language: C
File: nimble/host/src/ble_hs_hci_evt.c
Function: ble_hs_hci_evt_le_adv_rpt_first_pass

Call path: ble_hs_hci_evt_le_adv_rpt (nimble/host/src/ble_hs_hci_evt.c) → ble_hs_hci_evt_le_adv_rpt_first_pass (nimble/host/src/ble_hs_hci_evt.c) → ble_gap_rx_adv_report (nimble/host/src/ble_gap.c)

### Primary Function

```c
static int
ble_hs_hci_evt_le_adv_rpt_first_pass(const void *data, unsigned int len)
{
    const struct ble_hci_ev_le_subev_adv_rpt *ev = data;
    const struct adv_report *rpt;
    int i;

    if (len < sizeof(*ev)) {
        return BLE_HS_ECONTROLLER;
    }

    len -= sizeof(*ev);
    data += sizeof(*ev);

    if (ev->num_reports < BLE_HCI_LE_ADV_RPT_NUM_RPTS_MIN ||
        ev->num_reports > BLE_HCI_LE_ADV_RPT_NUM_RPTS_MAX) {
        return BLE_HS_EBADDATA;
    }

    for (i = 0; i < ev->num_reports; i++) {
        /* extra byte for RSSI after adv data */
        if (len < sizeof(*rpt) + 1) {
            return BLE_HS_ECONTROLLER;
        }

        rpt = data;

        len -= sizeof(*rpt) + 1;
        data += sizeof(rpt) + 1;

        if (rpt->data_len > len) {
            return BLE_HS_ECONTROLLER;
        }

        len -= rpt->data_len;
        data += rpt->data_len;
    }

    /* Make sure length was correct */
    if (len) {
        return BLE_HS_ECONTROLLER;
    }

    return 0;
}
```

### Cross-File Context

[adv_report — struct — nimble/include/nimble/hci_common.h:1860]
```c
struct adv_report {
    uint8_t type;
    uint8_t addr_type;
    uint8_t addr[6];
    uint8_t data_len;
    uint8_t data[0];
} __attribute__((packed));
```

[ble_hci_ev_le_subev_adv_rpt — struct — nimble/include/nimble/hci_common.h:1867]
```c
struct ble_hci_ev_le_subev_adv_rpt {
    uint8_t  subev_code;
    uint8_t  num_reports;
    struct adv_report reports[0];
} __attribute__((packed));
```

[BLE_HS_ECONTROLLER — constant — nimble/host/include/host/ble_hs.h:103]
BLE_HS_ECONTROLLER → 12  (nimble/host/include/host/ble_hs.h:103)

[BLE_HS_EBADDATA — constant — nimble/host/include/host/ble_hs.h:97]
BLE_HS_EBADDATA → 10  (nimble/host/include/host/ble_hs.h:97)

[BLE_HCI_LE_ADV_RPT_NUM_RPTS_MIN — constant — nimble/include/nimble/hci_common.h:2363]
BLE_HCI_LE_ADV_RPT_NUM_RPTS_MIN → (1)  (nimble/include/nimble/hci_common.h:2363)

[BLE_HCI_LE_ADV_RPT_NUM_RPTS_MAX — constant — nimble/include/nimble/hci_common.h:2364]
BLE_HCI_LE_ADV_RPT_NUM_RPTS_MAX → (0x19)  (nimble/include/nimble/hci_common.h:2364)

[ble_hs_hci_evt_le_adv_rpt — caller — nimble/host/src/ble_hs_hci_evt.c:505]
```c
static int
ble_hs_hci_evt_le_adv_rpt(uint8_t subevent, const void *data, unsigned int len)
{
    const struct ble_hci_ev_le_subev_adv_rpt *ev = data;
    struct ble_gap_disc_desc desc = {0};
    const struct adv_report *rpt;
    int rc;
    int i;

    /* Validate the event is formatted correctly */
    rc = ble_hs_hci_evt_le_adv_rpt_first_pass(data, len);
    if (rc != 0) {
        return rc;
    }

    data += sizeof(*ev);

    desc.direct_addr = *BLE_ADDR_ANY;

    for (i = 0; i < ev->num_reports; i++) {
        rpt = data;

        data += sizeof(*rpt) + rpt->data_len + 1;

        desc.event_type = rpt->type;
        desc.addr.type = rpt->addr_type;
        memcpy(desc.addr.val, rpt->addr, BLE_DEV_ADDR_LEN);
        desc.length_data = rpt->data_len;
        desc.data = rpt->data;
        desc.rssi = rpt->data[rpt->data_len];

        ble_gap_rx_adv_report(&desc);
    }

    return 0;
}
```

Control flow: ble_hs_hci_evt_le_adv_rpt calls ble_hs_hci_evt_le_adv_rpt_first_pass for validation. If validation passes (returns 0), the function proceeds to iterate over each report and call ble_gap_rx_adv_report for each. The vulnerable function loops over num_reports and performs pointer arithmetic to advance through the report data.

Data flow: Raw HCI event data flows from the controller through ble_hs_hci_evt_le_adv_rpt_first_pass for validation, then through ble_hs_hci_evt_le_adv_rpt for parsing. The bug affects the len (remaining length) and data (current position) variables used to track buffer boundaries during multi-report parsing.

Verdict: Vulnerable
Vulnerable region:
[nimble/host/src/ble_hs_hci_evt.c]
```c
rpt = data;

        len -= sizeof(*rpt) + 1;
        data += sizeof(rpt) + 1;

        if (rpt->data_len > len) {
            return BLE_HS_ECONTROLLER;
        }

        len -= rpt->data_len;
        data += rpt->data_len;
    }
```
CWE: CWE-125
Severity: MEDIUM

Root cause: In ble_hs_hci_evt_le_adv_rpt_first_pass, the expression 'data += sizeof(rpt) + 1' uses sizeof(rpt) which is the size of the pointer (8 bytes on 64-bit systems) instead of sizeof(*rpt) which is the actual size of the struct adv_report (9 bytes: 1+1+6+1 for type+addr_type+addr+data_len). This incorrect pointer arithmetic causes the validation to fail when processing events with more than one advertising report because the accumulated offset error compounds with each report processed.

Exploitability: The vulnerability is triggered when receiving a Bluetooth HCI event containing more than one advertising report. The controller sends multi-report events which fail validation due to the pointer arithmetic error, causing legitimate advertising data to be discarded.

Attack preconditions:
- Attacker must be able to send HCI events to the affected device
- The HCI event must contain more than one advertising report (num_reports >= 2)
- The event must be a legacy advertising report event (LE Advertising Report)

Likely impact: The vulnerability is triggered when receiving a Bluetooth HCI event containing more than one advertising report. The controller sends multi-report events which fail validation due to the pointer arithmetic error, causing legitimate advertising data to be discarded.

An audit of the provided code reveals a validation logic flaw that leads to an Out-of-Bounds (OOB) read vulnerability.

### Vulnerability Analysis
In `ble_hs_hci_evt_le_adv_rpt_first_pass`, the function performs a first pass over an HCI LE Advertising Report to validate its length before processing it. However, there is a typo in the pointer arithmetic used to advance the `data` pointer.

```c
        rpt = data;

        len -= sizeof(*rpt) + 1;    // Correctly subtracts structure size (9) + 1 = 10
        data += sizeof(rpt) + 1;    // INCORRECT: sizeof(rpt) is a pointer size (e.g., 4) + 1 = 5
```

Because `rpt` is a pointer (`const struct adv_report *rpt`), `sizeof(rpt)` evaluates to the size of a pointer (usually 4 bytes on a 32-bit embedded system) rather than the size of the structure (`sizeof(*rpt)`, which is 9 bytes).

As a result:
1. In the first iteration, `rpt` correctly points to the start of the report. The length check uses the correct `data_len`.
2. However, `data` is only advanced by 5 bytes (on 32-bit systems) instead of 10.
3. In the second (and subsequent) iterations, `rpt` will point to the wrong offset within the payload.
4. The validation pass reads `rpt->data_len` from this shifted offset. An attacker can craft a multi-report event (`num_reports > 1`) where the bytes at this shifted offset mathematically satisfy the strict length check (`if (len) { return BLE_HS_ECONTROLLER; }`).

If the attacker bypasses the validation pass, the second pass in the caller `ble_hs_hci_evt_le_adv_rpt` is executed. The caller uses the correct size to parse the reports:
```c
        data += sizeof(*rpt) + rpt->data_len + 1;
```
Because the validation pass used incorrect `data_len` fields from shifted offsets, the true `data_len` values parsed by the caller are entirely unvalidated. An attacker can supply a large `data_len` (e.g., 255) in the real structure, forcing the caller to read out-of-bounds memory:
```c
        desc.rssi = rpt->data[rpt->data_len]; // OOB Read
        // ... desc.data and desc.length_data passed to ble_gap_rx_adv_report
```

### Impact
An attacker in range can broadcast a malformed LE Advertising Report to trigger this bug. This causes the Bluetooth stack to read out of bounds. The immediate impact is likely a Denial of Service (DoS) due to a crash (reading unmapped memory). If the application reflects the out-of-bounds advertising data back to the network or a host interface, it may lead to an Information Disclosure of adjacent heap/stack memory.

### Root Cause
The pointer `data` is advanced by the size of the pointer (`sizeof(rpt)`) instead of the size of the referenced structure (`sizeof(*rpt)`).

### Remediation
Change `sizeof(rpt)` to `sizeof(*rpt)` in the `data += ...` expression inside `ble_hs_hci_evt_le_adv_rpt_first_pass`:

```c
-        data += sizeof(rpt) + 1;
+        data += sizeof(*rpt) + 1;
```

```json
{
    "vulnerable": true,
    "cwe": "CWE-125",
    "severity": "High",
    "reviewed_region": "ble_hs_hci_evt_le_adv_rpt_first_pass",
    "vulnerable_region": "len -= sizeof(*rpt) + 1;\ndata += sizeof(rpt) + 1;",
    "root_cause": "The pointer `data` is advanced by the size of the pointer (`sizeof(rpt)`) instead of the size of the referenced structure (`sizeof(*rpt)`).",
    "exploitability": "An attacker can craft a multi-report advertising event where the bytes at the shifted offsets (caused by the incorrect pointer arithmetic) mathematically satisfy the length validation. This bypasses the first pass length checks. The second pass in the caller function uses the correct arithmetic and parses unvalidated `data_len` values, leading to out-of-bounds reads.",
    "attack_preconditions": "The attacker must be within Bluetooth range and broadcast a specifically crafted LE Advertising Report with multiple reports (`num_reports > 1`).",
    "impact": "Out-of-bounds read leading to Denial of Service (crash from accessing unmapped memory) or Information Disclosure (if out-of-bounds heap/stack memory is processed and reflected).",
    "non_vulnerable_reason": "",
    "security_invariants": "",
    "invariant_verification": "",
    "residual_risk_notes": "",
    "call_path": "ble_hs_hci_evt_le_adv_rpt -> ble_hs_hci_evt_le_adv_rpt_first_pass -> ble_gap_rx_adv_report"
}
```


Audit the following candidate code to determine whether it presents a real vulnerability.
This sample may come from a noisy retrieval or transformation stage, so reason from the supplied code and context rather than assuming the label.

Repository: git.kernel.org/pub/scm/linux/kernel/git/stable/linux
Language: C
File: kernel/bpf/verifier.c
Function: adjust_scalar_min_max_vals

Call path: bpf_prog_load (kernel/bpf/syscall.c) → bpf_check (kernel/bpf/verifier.c) → check_alu_op (kernel/bpf/verifier.c) → adjust_scalar_min_max_vals (kernel/bpf/verifier.c) → adjust_ptr_min_max_vals (kernel/bpf/verifier.c)

### Primary Function

```c
static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env,
				      struct bpf_insn *insn,
				      struct bpf_reg_state *dst_reg,
				      struct bpf_reg_state src_reg)
{
	struct bpf_reg_state *regs = cur_regs(env);
	u8 opcode = BPF_OP(insn->code);
	bool src_known;
	s64 smin_val, smax_val;
	u64 umin_val, umax_val;
	s32 s32_min_val, s32_max_val;
	u32 u32_min_val, u32_max_val;
	u64 insn_bitness = (BPF_CLASS(insn->code) == BPF_ALU64) ? 64 : 32;
	bool alu32 = (BPF_CLASS(insn->code) != BPF_ALU64);
	int ret;

	smin_val = src_reg.smin_value;
	smax_val = src_reg.smax_value;
	umin_val = src_reg.umin_value;
	umax_val = src_reg.umax_value;

	s32_min_val = src_reg.s32_min_value;
	s32_max_val = src_reg.s32_max_value;
	u32_min_val = src_reg.u32_min_value;
	u32_max_val = src_reg.u32_max_value;

	if (alu32) {
		src_known = tnum_subreg_is_const(src_reg.var_off);
		if ((src_known &&
		     (s32_min_val != s32_max_val || u32_min_val != u32_max_val)) ||
		    s32_min_val > s32_max_val || u32_min_val > u32_max_val) {
			/* Taint dst register if offset had invalid bounds
			 * derived from e.g. dead branches.
			 */
			__mark_reg_unknown(env, dst_reg);
			return 0;
		}
	} else {
		src_known = tnum_is_const(src_reg.var_off);
		if ((src_known &&
		     (smin_val != smax_val || umin_val != umax_val)) ||
		    smin_val > smax_val || umin_val > umax_val) {
			/* Taint dst register if offset had invalid bounds
			 * derived from e.g. dead branches.
			 */
			__mark_reg_unknown(env, dst_reg);
			return 0;
		}
	}

	if (!src_known &&
	    opcode != BPF_ADD && opcode != BPF_SUB && opcode != BPF_AND) {
		__mark_reg_unknown(env, dst_reg);
		return 0;
	}

	if (sanitize_needed(opcode)) {
		ret = sanitize_val_alu(env, insn);
		if (ret < 0)
			return sanitize_err(env, insn, ret, NULL, NULL);
	}

	/* Calculate sign/unsigned bounds and tnum for alu32 and alu64 bit ops.
	 * There are two classes of instructions: The first class we track both
	 * alu32 and alu64 sign/unsigned bounds independently this provides the
	 * greatest amount of precision when alu operations are mixed with jmp32
	 * operations. These operations are BPF_ADD, BPF_SUB, BPF_MUL, BPF_ADD,
	 * and BPF_OR. This is possible because these ops have fairly easy to
	 * understand and calculate behavior in both 32-bit and 64-bit alu ops.
	 * See alu32 verifier tests for examples. The second class of
	 * operations, BPF_LSH, BPF_RSH, and BPF_ARSH, however are not so easy
	 * with regards to tracking sign/unsigned bounds because the bits may
	 * cross subreg boundaries in the alu64 case. When this happens we mark
	 * the reg unbounded in the subreg bound space and use the resulting
	 * tnum to calculate an approximation of the sign/unsigned bounds.
	 */
	switch (opcode) {
	case BPF_ADD:
		scalar32_min_max_add(dst_reg, &src_reg);
		scalar_min_max_add(dst_reg, &src_reg);
		dst_reg->var_off = tnum_add(dst_reg->var_off, src_reg.var_off);
		break;
	case BPF_SUB:
		scalar32_min_max_sub(dst_reg, &src_reg);
		scalar_min_max_sub(dst_reg, &src_reg);
		dst_reg->var_off = tnum_sub(dst_reg->var_off, src_reg.var_off);
		break;
	case BPF_MUL:
		dst_reg->var_off = tnum_mul(dst_reg->var_off, src_reg.var_off);
		scalar32_min_max_mul(dst_reg, &src_reg);
		scalar_min_max_mul(dst_reg, &src_reg);
		break;
	case BPF_AND:
		dst_reg->var_off = tnum_and(dst_reg->var_off, src_reg.var_off);
		scalar32_min_max_and(dst_reg, &src_reg);
		scalar_min_max_and(dst_reg, &src_reg);
		break;
	case BPF_OR:
		dst_reg->var_off = tnum_or(dst_reg->var_off, src_reg.var_off);
		scalar32_min_max_or(dst_reg, &src_reg);
		scalar_min_max_or(dst_reg, &src_reg);
		break;
	case BPF_XOR:
		dst_reg->var_off = tnum_xor(dst_reg->var_off, src_reg.var_off);
		scalar32_min_max_xor(dst_reg, &src_reg);
		scalar_min_max_xor(dst_reg, &src_reg);
		break;
	case BPF_LSH:
		if (umax_val >= insn_bitness) {
			/* Shifts greater than 31 or 63 are undefined.
			 * This includes shifts by a negative number.
			 */
			mark_reg_unknown(env, regs, insn->dst_reg);
			break;
		}
		if (alu32)
			scalar32_min_max_lsh(dst_reg, &src_reg);
		else
			scalar_min_max_lsh(dst_reg, &src_reg);
		break;
	case BPF_RSH:
		if (umax_val >= insn_bitness) {
			/* Shifts greater than 31 or 63 are undefined.
			 * This includes shifts by a negative number.
			 */
			mark_reg_unknown(env, regs, insn->dst_reg);
			break;
		}
		if (alu32)
			scalar32_min_max_rsh(dst_reg, &src_reg);
		else
			scalar_min_max_rsh(dst_reg, &src_reg);
		break;
	case BPF_ARSH:
		if (umax_val >= insn_bitness) {
			/* Shifts greater than 31 or 63 are undefined.
			 * This includes shifts by a negative number.
			 */
			mark_reg_unknown(env, regs, insn->dst_reg);
			break;
		}
		if (alu32)
			scalar32_min_max_arsh(dst_reg, &src_reg);
		else
			scalar_min_max_arsh(dst_reg, &src_reg);
		break;
	default:
		mark_reg_unknown(env, regs, insn->dst_reg);
		break;
	}

	/* ALU32 ops are zero extended into 64bit register */
	if (alu32)
		zext_32_to_64(dst_reg);
	reg_bounds_sync(dst_reg);
	return 0;
}
```

### Cross-File Context

[bpf_reg_state — struct — include/linux/bpf_verifier.h:46]
```c
struct bpf_reg_state {
	enum bpf_reg_type type;
	s32 off;
	union { ... };
	u32 id;
	u32 ref_obj_id;
	struct tnum var_off;
	s64 smin_value;
	s64 smax_value;
	u64 umin_value;
	u64 umax_value;
	s32 s32_min_value;
	s32 s32_max_value;
	u32 u32_min_value;
	u32 u32_max_value;
	struct bpf_reg_state *parent;
	...}
```

[tnum — struct — include/linux/tnum.h:14]
```c
struct tnum {
	u64 value;
	u64 mask;
};
```

[__update_reg_bounds — function — kernel/bpf/verifier.c:1471]
```c
static void __update_reg_bounds(struct bpf_reg_state *reg)
{
	__update_reg32_bounds(reg);
	__update_reg64_bounds(reg);
}
```

[__reg_deduce_bounds — function — kernel/bpf/verifier.c:1546]
```c
static void __reg_deduce_bounds(struct bpf_reg_state *reg)
{
	__reg32_deduce_bounds(reg);
	__reg64_deduce_bounds(reg);
}
```

[__reg_bound_offset — function — kernel/bpf/verifier.c:1553]
```c
static void __reg_bound_offset(struct bpf_reg_state *reg)
{
	struct tnum var64_off = tnum_intersect(reg->var_off,
					       tnum_range(reg->umin_value,
							  reg->umax_value));
	struct tnum var32_off = tnum_intersect(tnum_subreg(reg->var_off),
					tnum_range(reg->u32_min_value,
						   reg->u32_max_value));

	reg->var_off = tnum_or(tnum_clear_subreg(var64_off), var32_off);
}
```

[reg_bounds_sync — function — kernel/bpf/verifier.c:1565]
```c
static void reg_bounds_sync(struct bpf_reg_state *reg)
{
	/* We might have learned new bounds from the var_off. */
	__update_reg_bounds(reg);
	/* We might have learned something about the sign bit. */
	__reg_deduce_bounds(reg);
	/* We might have learned some bits from the bounds. */
	__reg_bound_offset(reg);
	/* Intersecting with the old var_off might have improved our bounds
	 * slightly, e.g. if umax was 0x7f...f and var_off was (0; 0xf...fc),
	 * then new var_off is (0; 0x7f...fc) which improves our umax.
	 */
	__update_reg_bounds(reg);
}
```

[SCALAR_VALUE — enum — include/linux/bpf.h:557]
SCALAR_VALUE, /* reg doesn't contain a valid pointer */

[BPF_OP — macro — include/uapi/linux/bpf_common.h:31]
BPF_OP → #define BPF_OP(code) ((code) & 0xf0)  (include/uapi/linux/bpf_common.h:31)

Control flow: The function extracts min/max bounds from the source register, then validates bounds consistency (checking smin<=smax, umin<=umax, and constancy constraints). If bounds are invalid, it marks dst_reg unknown and returns 0. If source is unknown for non-ADD/SUB/AND operations, it marks dst unknown and returns 0. The function then optionally sanitizes the instruction. A switch statement on opcode dispatches to operation-specific bound calculations (ADD, SUB, MUL, AND, OR, XOR, LSH, RSH, ARSH) or marks the register unknown for default/unsupported cases. Shift operations check that shift amounts don't exceed the instruction bitness. After the switch, ALU32 operations are zero-extended, then reg_bounds_sync is called before returning 0.

Data flow: Input: src_reg provides smin/smax/umin/umax/s32_min/s32_max/u32_min/u32_max bounds and var_off tnum. The instruction opcode determines the ALU operation. These inputs flow through operation-specific scalar32_min_max_* and scalar_min_max_* functions that compute new dst_reg bounds, and tnum_* operations that update dst_reg->var_off. Output: dst_reg's bound fields and var_off are updated, then synchronized via reg_bounds_sync which propagates information between var_off tnum and the scalar min/max fields.

Verdict: Not Vulnerable

Reviewed region:
[kernel/bpf/verifier.c]
```c
static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env,
				      struct bpf_insn *insn,
				      struct bpf_reg_state *dst_reg,
				      struct bpf_reg_state src_reg)
{
	struct bpf_reg_state *regs = cur_regs(env);
	u8 opcode = BPF_OP(insn->code);
	bool src_known;
	s64 smin_val, smax_val;
	u64 umin_val, umax_val;
	s32 s32_min_val, s32_max_val;
	u32 u32_min_val, u32_max_val;
	u64 insn_bitness = (BPF_CLASS(insn->code) == BPF_ALU64) ? 64 : 32;
	bool alu32 = (BPF_CLASS(insn->code) != BPF_ALU64);
	int ret;

	smin_val = src_reg.smin_value;
	smax_val = src_reg.smax_value;
	umin_val = src_reg.umin_value;
	umax_val = src_reg.umax_value;

	s32_min_val = src_reg.s32_min_value;
	s32_max_val = src_reg.s32_max_value;
	u32_min_val = src_reg.u32_min_value;
	u32_max_val = src_reg.u32_max_value;

	if (alu32) {
		src_known = tnum_subreg_is_const(src_reg.var_off);
		if ((src_known &&
		     (s32_min_val != s32_max_val || u32_min_val != u32_max_val)) ||
		    s32_min_val > s32_max_val || u32_min_val > u32_max_val) {
			/* Taint dst register if offset had invalid bounds
			 * derived from e.g. dead branches.
			 */
			__mark_reg_unknown(env, dst_reg);
			return 0;
		}
	} else {
		src_known = tnum_is_const(src_reg.var_off);
		if ((src_known &&
		     (smin_val != smax_val || umin_val != umax_val)) ||
		    smin_val > smax_val || umin_val > umax_val) {
			/* Taint dst register if offset had invalid bounds
			 * derived from e.g. dead branches.
			 */
			__mark_reg_unknown(env, dst_reg);
			return 0;
		}
	}

	if (!src_known &&
	    opcode != BPF_ADD && opcode != BPF_SUB && opcode != BPF_AND) {
		__mark_reg_unknown(env, dst_reg);
		return 0;
	}

	if (sanitize_needed(opcode)) {
		ret = sanitize_val_alu(env, insn);
		if (ret < 0)
			return sanitize_err(env, insn, ret, NULL, NULL);
	}

	/* Calculate sign/unsigned bounds and tnum for alu32 and alu64 bit ops.
	 * There are two classes of instructions: The first class we track both
	 * alu32 and alu64 sign/unsigned bounds independently this provides the
	 * greatest amount of precision when alu operations are mixed with jmp32
	 * operations. These operations are BPF_ADD, BPF_SUB, BPF_MUL, BPF_ADD,
	 * and BPF_OR. This is possible because these ops have fairly easy to
	 * understand and calculate behavior in both 32-bit and 64-bit alu ops.
	 * See alu32 verifier tests for examples. The second class of
	 * operations, BPF_LSH, BPF_RSH, and BPF_ARSH, however are not so easy
	 * with regards to tracking sign/unsigned bounds because the bits may
	 * cross subreg boundaries in the alu64 case. When this happens we mark
	 * the reg unbounded in the subreg bound space and use the resulting
	 * tnum to calculate an approximation of the sign/unsigned bounds.
	 */
	switch (opcode) {
	case BPF_ADD:
		scalar32_min_max_add(dst_reg, &src_reg);
		scalar_min_max_add(dst_reg, &src_reg);
		dst_reg->var_off = tnum_add(dst_reg->var_off, src_reg.var_off);
		break;
	case BPF_SUB:
		scalar32_min_max_sub(dst_reg, &src_reg);
		scalar_min_max_sub(dst_reg, &src_reg);
		dst_reg->var_off = tnum_sub(dst_reg->var_off, src_reg.var_off);
		break;
	case BPF_MUL:
		dst_reg->var_off = tnum_mul(dst_reg->var_off, src_reg.var_off);
		scalar32_min_max_mul(dst_reg, &src_reg);
		scalar_min_max_mul(dst_reg, &src_reg);
		break;
	case BPF_AND:
		dst_reg->var_off = tnum_and(dst_reg->var_off, src_reg.var_off);
		scalar32_min_max_and(dst_reg, &src_reg);
		scalar_min_max_and(dst_reg, &src_reg);
		break;
	case BPF_OR:
		dst_reg->var_off = tnum_or(dst_reg->var_off, src_reg.var_off);
		scalar32_min_max_or(dst_reg, &src_reg);
		scalar_min_max_or(dst_reg, &src_reg);
		break;
	case BPF_XOR:
		dst_reg->var_off = tnum_xor(dst_reg->var_off, src_reg.var_off);
		scalar32_min_max_xor(dst_reg, &src_reg);
		scalar_min_max_xor(dst_reg, &src_reg);
		break;
	case BPF_LSH:
		if (umax_val >= insn_bitness) {
			/* Shifts greater than 31 or 63 are undefined.
			 * This includes shifts by a negative number.
			 */
			mark_reg_unknown(env, regs, insn->dst_reg);
			break;
		}
		if (alu32)
			scalar32_min_max_lsh(dst_reg, &src_reg);
		else
			scalar_min_max_lsh(dst_reg, &src_reg);
		break;
	case BPF_RSH:
		if (umax_val >= insn_bitness) {
			/* Shifts greater than 31 or 63 are undefined.
			 * This includes shifts by a negative number.
			 */
			mark_reg_unknown(env, regs, insn->dst_reg);
			break;
		}
		if (alu32)
			scalar32_min_max_rsh(dst_reg, &src_reg);
		else
			scalar_min_max_rsh(dst_reg, &src_reg);
		break;
	case BPF_ARSH:
		if (umax_val >= insn_bitness) {
			/* Shifts greater than 31 or 63 are undefined.
			 * This includes shifts by a negative number.
			 */
			mark_reg_unknown(env, regs, insn->dst_reg);
			break;
		}
		if (alu32)
			scalar32_min_max_arsh(dst_reg, &src_reg);
		else
			scalar_min_max_arsh(dst_reg, &src_reg);
		break;
	default:
		mark_reg_unknown(env, regs, insn->dst_reg);
		break;
	}

	/* ALU32 ops are zero extended into 64bit register */
	if (alu32)
		zext_32_to_64(dst_reg);
	reg_bounds_sync(dst_reg);
	return 0;
}
```

Why it is not vulnerable: The function consistently calls reg_bounds_sync(dst_reg) at the end of the normal execution path, after all switch-case operations that modify dst_reg->var_off and scalar bounds. This ensures that after any operation refines the variable offset (tnum), the min/max values are synchronized to remain consistent. Early return paths either mark the register as unknown (a terminal state that doesn't require further bound tracking) or return an error from sanitization. The reg_bounds_sync function performs a multi-pass reconciliation: it updates bounds from var_off, deduces sign bit information, propagates bit knowledge to var_off, and performs a final bounds update.

Security invariants:
- After modifying dst_reg->var_off in any switch case, bounds must be synchronized to ensure min/max values remain consistent with the tnum state. Enforced by the unconditional reg_bounds_sync(dst_reg) call at the end of the function before the normal return.
- Register marked as unknown represents a terminal unknown state; bounds need not be further refined. Enforced by __mark_reg_unknown marking the register unknown and returning early, and by mark_reg_unknown in shift overflow cases and default case.
- Shift operations must not allow undefined shift amounts (>= bitness). Enforced by the umax_val >= insn_bitness checks in BPF_LSH, BPF_RSH, and BPF_ARSH cases, which mark the register unknown when violated.
- Source register bounds must be consistent (smin <= smax, umin <= umax) and match constancy expectations. Enforced by the bounds validation checks at the start that mark dst unknown if inconsistencies exist.

Invariant verification:
- Bounds synchronization after var_off refinement: holds=true. Evidence: Every switch case that modifies dst_reg->var_off (ADD, SUB, MUL, AND, OR, XOR, and the non-overflow paths of LSH/RSH/ARSH) falls through to reg_bounds_sync(dst_reg) at the end of the function before return 0. Cases that cannot compute bounds (shift overflow, default opcode) call mark_reg_unknown and break, reaching reg_bounds_sync which handles the unknown state.
- Early return paths do not leave inconsistent partial state: holds=true. Evidence: The two early return paths (invalid source bounds check and sanitize error) both occur before any modification to dst_reg's bound fields. The invalid bounds path calls __mark_reg_unknown(env, dst_reg) to transition dst to unknown state before returning. The sanitize path returns an error code preventing continued execution.
- ALU32 zero-extension applied before synchronization: holds=true. Evidence: The if (alu32) zext_32_to_64(dst_reg) call occurs after the switch statement and before reg_bounds_sync(dst_reg), ensuring zero-extension effects are incorporated before bounds reconciliation.

Residual risk notes: The correctness of bounds synchronization depends on the internal correctness of scalar_min_max_* functions and tnum_* operations. Additionally, when mark_reg_unknown is called for shift overflow, the function still proceeds to reg_bounds_sync on the now-unknown register, which is benign but represents redundant computation. The function trusts that sanitize_val_alu properly handles its designated sanitization responsibilities.

Based on the provided code and context, there does not appear to be a vulnerability in this function. The logic in `adjust_scalar_min_max_vals` safely handles edge cases by gracefully degrading precision (overestimating bounds) and ensuring that the verifier's state conservatively models the execution behavior.

### Analysis of the Checked Paths

1. **Shift operations with unknown amounts or excessive lengths:**
   When handling `BPF_LSH`, `BPF_RSH`, and `BPF_ARSH`, the verifier correctly bounds checks the shift amount using `umax_val >= insn_bitness` (i.e. shift amounts of 32/64 or greater, which could result in architecture-specific undefined behavior). If the shift amount could exceed the register width, the destination register bounds are conservatively wiped out by breaking out with `mark_reg_unknown()`. This securely avoids misaligned state deductions between eBPF boundaries and JIT-compiled native execution boundaries.

2. **Early Returns for Non-Trackable Registers:**
   If `src_known` (whether the source register has a known constant state based on `tnum_subreg_is_const` or `tnum_is_const`) evaluates to false, and the opcode falls into more complex tracking categories (like `BPF_MUL`, `BPF_OR`, `BPF_XOR`, and shifts), the function calls `__mark_reg_unknown(env, dst_reg)` and immediately returns `0`.

   While skipping the bottom block skips `zext_32_to_64(dst_reg)` for `alu32` instructions, the result is that the verifier assumes the register contains a fully unknown 64-bit value rather than a 32-bit zero-extended value. Because a completely unbounded 64-bit state is a strict superset of all potential 32-bit zero-extended values, this acts as a safe overestimation. The verifier denies any risky operations utilizing that register down the line, maintaining safety invariants.

3. **Bounds Synchronization:**
   For safely trackable operations (such as `BPF_ADD`, `BPF_SUB`, `BPF_AND`), and shifts with valid bounds, the code invokes dedicated scalar min-max helper functions. It successfully propagates state changes and invokes `reg_bounds_sync(dst_reg)` to realign `var_off`, 32-bit bounds, and 64-bit bounds together safely without causing deduction mismatches.

### Verdict
The code is securely designed. It appropriately sacrifices precision for safety by using `mark_reg_unknown()` upon detecting invalid or overly complex operand states, effectively eliminating the risk of out-of-bounds speculation or faulty deductions within this function's scope.

```json
{
  "vulnerable": false,
  "cwe": "N/A",
  "severity": "N/A",
  "reviewed_region": "adjust_scalar_min_max_vals",
  "vulnerable_region": "N/A",
  "root_cause": "N/A",
  "exploitability": "N/A",
  "attack_preconditions": "N/A",
  "impact": "N/A",
  "non_vulnerable_reason": "The function correctly protects against unsupported or potentially invalid operations by resetting the destination register to a completely unknown state (__mark_reg_unknown). While some early return paths for ALU32 operations skip the explicit zext_32_to_64() step, an unbounded 64-bit unknown state is a strict mathematical superset of a 32-bit zero-extended unknown state. Consequently, the verifier's assumptions are strictly more conservative than the runtime behavior, preventing out-of-bounds access or unsafe memory deductions at the cost of rejecting some valid programs.",
  "security_invariants": [
    "Any register state with invalid bounds or unsupported operand configurations must be downgraded to a state that encompasses all possible runtime values.",
    "Fully unknown 64-bit scalar states must safely encompass any zero-extended 32-bit runtime values."
  ],
  "invariant_verification": [
    "The use of __mark_reg_unknown / mark_reg_unknown correctly sets all bounds to their maximum theoretical ranges (e.g., [S64_MIN, S64_MAX]).",
    "Shift amounts >= insn_bitness break out of the switch and appropriately mark the register unknown before properly zero-extending (if applicable) and syncing."
  ],
  "residual_risk_notes": "The analysis assumes that __mark_reg_unknown correctly resets all 32-bit and 64-bit state boundaries to their maximal unbounded values, without leaving any legacy state that could confuse reg_bounds_sync in later operations.",
  "call_path": "bpf_prog_load (kernel/bpf/syscall.c) \u2192 bpf_check (kernel/bpf/verifier.c) \u2192 check_alu_op (kernel/bpf/verifier.c) \u2192 adjust_scalar_min_max_vals (kernel/bpf/verifier.c) \u2192 adjust_ptr_min_max_vals (kernel/bpf/verifier.c)"
}
```