The maximum number of times a callsite can appear in a call stack within the analyzer, before terminating analysis of a call that would recurse deeper.
-param=analyzer-max-svalue-depth=
-Common Joined UInteger Var(param_analyzer_max_svalue_depth) Init(12) Param
+Common Joined UInteger Var(param_analyzer_max_svalue_depth) Init(18) Param
The maximum depth of a symbolic value, before approximating the value as unknown.
-param=analyzer-min-snodes-for-call-summary=
Common Var(warn_analyzer_use_of_uninitialized_value) Init(1) Warning
Warn about code paths in which an uninitialized value is used.
+Wanalyzer-symbol-too-complex
+Common Var(warn_analyzer_symbol_too_complex) Init(0) Warning
+Warn if expressions are too complicated for the analyzer to fully track.
+
Wanalyzer-too-complex
Common Var(warn_analyzer_too_complex) Init(0) Warning
Warn if the code is too complicated for the analyzer to fully explore.
/* No-op. */
}
+ void clear_all_per_svalue_state () final override
+ {
+ /* No-op. */
+ }
+
void on_custom_transition (custom_transition *) final override
{
}
m_new_state->m_checker_states[m_sm_idx]->set_global_state (state);
}
+ void clear_all_per_svalue_state () final override
+ {
+ m_new_state->m_checker_states[m_sm_idx]->clear_all_per_svalue_state ();
+ }
+
void on_custom_transition (custom_transition *transition) final override
{
transition->impl_transition (&m_eg,
m_map.remove (sval);
}
+/* Clear all per-svalue state within this state map. */
+
+void
+sm_state_map::clear_all_per_svalue_state ()
+{
+ m_map.empty ();
+}
+
/* Set the "global" state within this state map to STATE. */
void
const svalue *origin,
const extrinsic_state &ext_state);
void clear_any_state (const svalue *sval);
+ void clear_all_per_svalue_state ();
void set_global_state (state_machine::state_t state);
state_machine::state_t get_global_state () const;
return false;
}
+ pretty_printer pp;
+ pp_format_decoder (&pp) = default_tree_printer;
+ sval->dump_to_pp (&pp, true);
+ if (warning_at (input_location, OPT_Wanalyzer_symbol_too_complex,
+ "symbol too complicated: %qs",
+ pp_formatted_text (&pp)))
+ inform (input_location,
+ "max_depth %i exceeds --param=analyzer-max-svalue-depth=%i",
+ c.m_max_depth, param_analyzer_max_svalue_depth);
+
delete sval;
return true;
}
if (stmt == NULL)
return;
+ if (lhs->get_kind () == SK_UNKNOWN
+ || rhs->get_kind () == SK_UNKNOWN)
+ {
+ /* If we have a comparison against UNKNOWN, then
+ we've presumably hit the svalue complexity limit,
+ and we don't know what is being sanitized.
+ Give up on any taint already found on this execution path. */
+ // TODO: warn about this
+ if (get_logger ())
+ get_logger ()->log ("comparison against UNKNOWN; removing all taint");
+ sm_ctxt->clear_all_per_svalue_state ();
+ return;
+ }
+
// TODO
switch (op)
{
virtual state_machine::state_t get_global_state () const = 0;
virtual void set_global_state (state_machine::state_t) = 0;
+ virtual void clear_all_per_svalue_state () = 0;
+
/* A vfunc for handling custom transitions, such as when registering
a signal handler. */
virtual void on_custom_transition (custom_transition *transition) = 0;
-Wno-analyzer-tainted-divisor
-Wno-analyzer-tainted-offset
-Wno-analyzer-tainted-size
+-Wanalyzer-symbol-too-complex
-Wanalyzer-too-complex
-Wno-analyzer-undefined-behavior-strtok
-Wno-analyzer-unsafe-call-within-signal-handler
This option is only available if GCC was configured with analyzer
support enabled.
+@opindex Wanalyzer-symbol-too-complex
+@opindex Wno-analyzer-symbol-too-complex
+@item -Wanalyzer-symbol-too-complex
+If @option{-fanalyzer} is enabled, the analyzer uses various heuristics
+to attempt to track the state of memory, but these can be defeated by
+sufficiently complicated code.
+
+By default, the analysis silently stops tracking values of expressions
+if they exceed the threshold defined by
+@option{--param analyzer-max-svalue-depth=@var{value}}, and falls back
+to an imprecise representation for such expressions.
+The @option{-Wanalyzer-symbol-too-complex} option warns if this occurs.
+
@opindex Wanalyzer-too-complex
@opindex Wno-analyzer-too-complex
@item -Wanalyzer-too-complex
-/* { dg-additional-options "-fanalyzer-call-summaries -Wno-analyzer-too-complex" } */
+/* { dg-additional-options "-fanalyzer-call-summaries -Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex" } */
/* { dg-skip-if "c++98 has no noreturn attribute" { c++98_only } } */
#ifdef __cplusplus
-/* { dg-additional-options "-fanalyzer-call-summaries" } */
+/* { dg-additional-options "-fanalyzer-call-summaries -Wno-analyzer-symbol-too-complex" } */
typedef __SIZE_TYPE__ size_t;
enum { _ISspace = ((5) < 8 ? ((1 << (5)) << 8) : ((1 << (5)) >> 8)) };
/* Reduced from haproxy-2.7.1's cfgparse.c. */
+/* { dg-additional-options "-Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex" } */
+
typedef __SIZE_TYPE__ size_t;
extern int
/* Reduced and adapted from Linux: fs/proc/inode.c: proc_reg_open
(GPL v2.0). */
+/* { dg-additional-options "-Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex" } */
+
/* Types. */
typedef unsigned char u8;
/* { dg-skip-if "" { "avr-*-*" } } */
/* { dg-additional-options "-fanalyzer-call-summaries" } */
/* { dg-additional-options "-Wno-analyzer-too-complex" } */
+/* { dg-additional-options "-Wno-analyzer-symbol-too-complex" } */
/* A lexical scanner generated by flex */
}
else
/* Can't grow it, we don't own it. */
- b->yy_ch_buf = NULL; /* { dg-bogus "leak" "" { xfail *-*-* } } */
- /* TODO: leak false positive: PR analyzer/103546. */
+ b->yy_ch_buf = NULL; /* { dg-bogus "leak" "PR analyzer/103546" } */
if ( ! b->yy_ch_buf )
YY_FATAL_ERROR(
}
else
/* Can't grow it, we don't own it. */
- b->yy_ch_buf = NULL; /* { dg-bogus "leak" "" { xfail *-*-* } } */
- /* TODO: leak false positive: PR analyzer/103546. */
+ b->yy_ch_buf = NULL; /* { dg-bogus "leak" "PR analyzer/103546" */
if ( ! b->yy_ch_buf )
YY_FATAL_ERROR(
-/* { dg-additional-options "-fno-analyzer-call-summaries -Wno-analyzer-too-complex" } */
+/* { dg-additional-options "-fno-analyzer-call-summaries -Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex" } */
struct node
{
/* Reduced from haproxy's src/ssl_sample.c */
/* { dg-require-effective-target ptr_eq_long } */
-/* { dg-additional-options "-O2" } */
+/* { dg-additional-options "-O2 -Wno-analyzer-symbol-too-complex" } */
union sample_value {
long long int sint;
/* Reduced from haproxy's src/ssl_sample.c */
/* { dg-require-effective-target ptr_eq_long } */
+/* { dg-additional-options "-Wno-analyzer-symbol-too-complex" } */
union sample_value {
long long int sint;
/* Reduced from SoftEtherVPN's src/Cedar/WebUI.c. */
+/* { dg-additional-options "-Wno-analyzer-symbol-too-complex" } */
+
#include "../../gcc.dg/analyzer/analyzer-decls.h"
typedef int (COMPARE)(void *p1, void *p2);
typedef unsigned int UINT;
/* Reduced from qemu-7.2.0's hw/intc/omap_intc.c */
+/* { dg-additional-options "-Wno-analyzer-symbol-too-complex" } */
+
#include "../../gcc.dg/analyzer/analyzer-decls.h"
typedef unsigned char __uint8_t;
/* Reduced from apr-1.7.0/tables/apr_hash.c: 'apr_hash_merge' */
-/* { dg-additional-options "-Wno-analyzer-too-complex" } */
+/* { dg-additional-options "-Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex" } */
#include "../../gcc.dg/analyzer/analyzer-decls.h"
*/
#include "../../gcc.dg/analyzer/analyzer-decls.h"
+
+/* { dg-additional-options "-Wno-analyzer-symbol-too-complex" } */
+
typedef __SIZE_TYPE__ size_t;
#ifndef __cplusplus
+/* { dg-additional-options "-Wno-analyzer-symbol-too-complex" } */
+
#include "../../gcc.dg/analyzer/analyzer-decls.h"
extern char *strtok (char *str, const char *delim)
+/* { dg-additional-options "-Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex" } */
+
#include "../../gcc.dg/analyzer/analyzer-decls.h"
extern char *strtok (char *str, const char *delim);
should be released under an equivalent license so that everyone could
benefit from the modified versions. " */
+/* { dg-additional-options " -Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex" } */
+
#define __STDC_WANT_LIB_EXT1__ 0
#include <string.h>
#include <stdio.h>
}
# If a testcase doesn't have special options, use these.
-set DEFAULT_CFLAGS "-fanalyzer -Wanalyzer-too-complex -fanalyzer-call-summaries"
+set DEFAULT_CFLAGS "-fanalyzer -Wanalyzer-too-complex -Wanalyzer-symbol-too-complex -fanalyzer-call-summaries"
if { [istarget "*-*-darwin*" ] } {
# On macOS, system headers redefine by default some macros (memcpy,
/* Verify that we handle unknown values passed to __attribute__ ((const))
(by imposing a complexity limit). */
-/* { dg-additional-options "--param analyzer-max-svalue-depth=4" } */
+/* { dg-additional-options "--param analyzer-max-svalue-depth=4 -Wno-analyzer-symbol-too-complex" } */
#include "analyzer-decls.h"
/* { dg-require-effective-target int32plus } */
-/* { dg-additional-options "-fanalyzer-call-summaries --param analyzer-min-snodes-for-call-summary=0" } */
+/* { dg-additional-options "-fanalyzer-call-summaries --param analyzer-min-snodes-for-call-summary=0 -Wno-analyzer-symbol-too-complex" } */
/* There need to be at least two calls to a function for the
call-summarization code to be used.
/* Reduced from Doom's linuxdoom-1.10/s_sound.c, which is GPLv2 or later. */
-/* { dg-additional-options "-fno-analyzer-call-summaries -Wno-analyzer-too-complex" } */
+/* { dg-additional-options "-fno-analyzer-call-summaries -Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex" } */
/* { dg-require-effective-target size32plus } */
typedef struct _IO_FILE FILE;
conjured_svalues whilst handling a long chain of external
function calls. */
-/* { dg-additional-options "-Wno-implicit-function-declaration -Wno-int-conversion -Wno-analyzer-too-complex" } */
+/* { dg-additional-options "-Wno-implicit-function-declaration -Wno-int-conversion -Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex" } */
#define NULL ((void *)0)
typedef unsigned char uint8_t;
/* { dg-require-effective-target ptr_eq_long } */
-/* { dg-additional-options "-O2 -Wno-shift-count-overflow" } */
+/* { dg-additional-options "-O2 -Wno-shift-count-overflow -Wno-analyzer-symbol-too-complex" } */
struct lisp;
union vectorlike_header { long size; };
/* { dg-require-effective-target int32plus } */
-/* { dg-additional-options "-Wno-analyzer-too-complex -O2" } */
+/* { dg-additional-options "-Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex -O2" } */
typedef long int ptrdiff_t;
typedef long int EMACS_INT;
-/* { dg-additional-options "-O2" } */
+/* { dg-additional-options "-O2 -Wno-analyzer-symbol-too-complex" } */
#include <string.h>
/* Reduced from curl lib/smb.c. */
-/* { dg-additional-options "--param analyzer-max-svalue-depth=0" } */
+/* { dg-additional-options "--param analyzer-max-svalue-depth=0 -Wno-analyzer-symbol-too-complex" } */
int val;
-/* { dg-additional-options "-O2" } */
+/* { dg-additional-options "-O2 -Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex" } */
/* C only: C++ FE optimizes argstr_get_word completely away
and therefore the number of SN diminishes compared to C,
-/* { dg-additional-options "-O2" } */
+/* { dg-additional-options "-O2 -Wno-analyzer-symbol-too-complex" } */
#include <stdlib.h>
/* { dg-require-effective-target int128 } */
-/* { dg-additional-options "--param analyzer-max-svalue-depth=0" } */
+/* { dg-additional-options "--param analyzer-max-svalue-depth=0 -Wno-analyzer-symbol-too-complex" } */
void x7 (void)
{
-/* { dg-additional-options "--param analyzer-max-svalue-depth=0" } */
+/* { dg-additional-options "--param analyzer-max-svalue-depth=0 -Wno-analyzer-symbol-too-complex" } */
void x7 (void)
{
+/* { dg-additional-options "-Wno-analyzer-symbol-too-complex" } */
+
#include <stdlib.h>
struct marker {
+/* { dg-additional-options "-Wno-analyzer-symbol-too-complex" } */
+
struct node
{
struct node *next;
struct omap_intr_handler_bank_s* bank;
*/
+/* { dg-additional-options "-Wno-analyzer-symbol-too-complex" } */
+
typedef unsigned char __uint8_t;
typedef unsigned int __uint32_t;
typedef unsigned long int __uint64_t;
+/* { dg-additional-options "-Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex" } */
+
#include <stdlib.h>
#include "analyzer-decls.h"
taint-CVE-2011-0521-5.c \
taint-CVE-2011-0521-5-fixed.c \
taint-CVE-2011-0521-6.c \
- taint-antipatterns-1.c } \
+ taint-antipatterns-1.c \
+ taint-pr112850.c \
+ taint-pr112850-precise.c \
+ taint-pr112850-too-complex.c \
+ taint-pr112850-unsanitized.c } \
{ analyzer_cpython_plugin.c \
cpython-plugin-test-no-Python-h.c \
cpython-plugin-test-PyList_Append.c \
if (info->num > 1)
return -EINVAL;
av7110->ci_slot[info->num].num = info->num; /* { dg-warning "attacker-controlled value" } */
- av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ? /* { dg-warning "attacker-controlled value" } */
+ av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ?
CA_CI_LINK : CA_CI;
- memcpy(info, &av7110->ci_slot[info->num], sizeof(ca_slot_info_t)); /* { dg-warning "attacker-controlled value" } */
+ memcpy(info, &av7110->ci_slot[info->num], sizeof(ca_slot_info_t));
}
copy_to_user((void __user *)arg, parg, sizeof(sbuf));
av7110->ci_slot[info->num].num = info->num;
av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ?
CA_CI_LINK : CA_CI;
- memcpy(info, &av7110->ci_slot[info->num], sizeof(ca_slot_info_t)); /* { dg-bogus "use of attacker-controlled value in array lookup without bounds checking" "" { xfail *-*-* } } */
- // FIXME: why the above false +ve?
+ memcpy(info, &av7110->ci_slot[info->num], sizeof(ca_slot_info_t)); /* { dg-bogus "use of attacker-controlled value in array lookup without bounds checking" } */
}
copy_to_user((void __user *)arg, &sbuf, sizeof(sbuf));
__analyzer_dump_state ("taint", info->num); /* { dg-warning "has_ub" } */
av7110->ci_slot[info->num].num = info->num; /* { dg-warning "use of attacker-controlled value '\\*info\\.num' in array lookup without checking for negative" } */
- av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ? /* { dg-warning "use of attacker-controlled value '\\*info\\.num' in array lookup without checking for negative" } */
+ av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ?
CA_CI_LINK : CA_CI;
- memcpy(info, &av7110->ci_slot[info->num], sizeof(ca_slot_info_t)); /* { dg-warning "use of attacker-controlled value in array lookup without bounds checking" } */
+ memcpy(info, &av7110->ci_slot[info->num], sizeof(ca_slot_info_t));
}
copy_to_user((void __user *)arg, &sbuf, sizeof(sbuf));
//__analyzer_break ();
av7110->ci_slot[info->num].num = info->num; /* { dg-warning "use of attacker-controlled value '\\*info\\.num' in array lookup without bounds checking" } */
- av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ? /* { dg-warning "use of attacker-controlled value '\\*info\\.num' in array lookup without bounds checking" } */
+ av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ?
CA_CI_LINK : CA_CI;
- memcpy(info, &av7110->ci_slot[info->num], sizeof(ca_slot_info_t)); /* { dg-warning "use of attacker-controlled value in array lookup without bounds checking" } */
+ memcpy(info, &av7110->ci_slot[info->num], sizeof(ca_slot_info_t));
}
copy_to_user((void __user *)arg, &sbuf, sizeof(sbuf));
--- /dev/null
+/* Reduced from false positive in Linux kernel in sound/core/rawmidi.c.
+
+ Use a value of --param=analyzer-max-svalue-depth= high enough to avoid
+ UNKNOWN svalues; make sure we don't get false positives with this case. */
+
+/* { dg-do compile } */
+/* { dg-options "-fanalyzer -O2 -Wanalyzer-symbol-too-complex --param=analyzer-max-svalue-depth=13" } */
+/* { dg-require-effective-target analyzer } */
+
+typedef unsigned long __kernel_ulong_t;
+typedef __kernel_ulong_t __kernel_size_t;
+typedef __kernel_size_t size_t;
+typedef unsigned int gfp_t;
+
+extern unsigned long copy_from_user(void* to, const void* from, unsigned long n);
+
+extern
+__attribute__((__alloc_size__(1)))
+__attribute__((__malloc__)) void*
+kvzalloc(size_t size, gfp_t flags);
+
+struct snd_rawmidi_params
+{
+ int stream;
+ size_t buffer_size;
+};
+
+char *newbuf;
+
+static int
+resize_runtime_buffer(struct snd_rawmidi_params* params)
+{
+ if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L) /* { dg-bogus "symbol too complicated" } */
+ return -22;
+ newbuf = kvzalloc(params->buffer_size, /* { dg-bogus "use of attacker-controlled value '\\*params.buffer_size' as allocation size without upper-bounds checking" "PR analyzer/112850" } */
+ (((gfp_t)(0x400u | 0x800u)) | ((gfp_t)0x40u) | ((gfp_t)0x80u)));
+ if (!newbuf)
+ return -12;
+ return 0;
+}
+
+long
+snd_rawmidi_ioctl(unsigned long arg)
+{
+ void* argp = (void*)arg;
+ struct snd_rawmidi_params params;
+ if (copy_from_user(¶ms, argp, sizeof(struct snd_rawmidi_params)))
+ return -14;
+ return resize_runtime_buffer(¶ms);
+}
--- /dev/null
+/* Reduced from false positive in Linux kernel in sound/core/rawmidi.c.
+
+ With --param=analyzer-max-svalue-depth=12, the value being compared
+ at the sanitization is too complex and becomes UNKNOWN; make sure
+ this doesn't lead to a false positive. */
+
+/* { dg-do compile } */
+/* { dg-options "-fanalyzer -O2 -Wanalyzer-symbol-too-complex --param=analyzer-max-svalue-depth=12" } */
+/* { dg-require-effective-target analyzer } */
+
+typedef unsigned long __kernel_ulong_t;
+typedef __kernel_ulong_t __kernel_size_t;
+typedef __kernel_size_t size_t;
+typedef unsigned int gfp_t;
+
+extern unsigned long copy_from_user(void* to, const void* from, unsigned long n);
+
+extern
+__attribute__((__alloc_size__(1)))
+__attribute__((__malloc__)) void*
+kvzalloc(size_t size, gfp_t flags);
+
+struct snd_rawmidi_params
+{
+ int stream;
+ size_t buffer_size;
+};
+
+char *newbuf;
+
+static int
+resize_runtime_buffer(struct snd_rawmidi_params* params)
+{
+ if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L) /* { dg-warning "symbol too complicated" } */
+ return -22;
+ newbuf = kvzalloc(params->buffer_size, /* { dg-bogus "use of attacker-controlled value '\\*params.buffer_size' as allocation size without upper-bounds checking" "PR analyzer/112850" } */
+ (((gfp_t)(0x400u | 0x800u)) | ((gfp_t)0x40u) | ((gfp_t)0x80u)));
+ if (!newbuf)
+ return -12;
+ return 0;
+}
+
+long
+snd_rawmidi_ioctl(unsigned long arg)
+{
+ void* argp = (void*)arg;
+ struct snd_rawmidi_params params;
+ if (copy_from_user(¶ms, argp, sizeof(struct snd_rawmidi_params)))
+ return -14;
+ return resize_runtime_buffer(¶ms);
+}
--- /dev/null
+/* Reduced from false positive in Linux kernel in sound/core/rawmidi.c,
+ with sanitization removed to make it a true positive.
+
+ Verify that we detect this (with default params). */
+
+/* { dg-do compile } */
+/* { dg-options "-fanalyzer -O2 -Wanalyzer-too-complex" } */
+/* { dg-require-effective-target analyzer } */
+
+typedef unsigned long __kernel_ulong_t;
+typedef __kernel_ulong_t __kernel_size_t;
+typedef __kernel_size_t size_t;
+typedef unsigned int gfp_t;
+
+extern unsigned long copy_from_user(void* to, const void* from, unsigned long n);
+
+extern
+__attribute__((__alloc_size__(1)))
+__attribute__((__malloc__)) void*
+kvzalloc(size_t size, gfp_t flags);
+
+struct snd_rawmidi_params
+{
+ int stream;
+ size_t buffer_size;
+};
+
+char *newbuf;
+
+static int
+resize_runtime_buffer(struct snd_rawmidi_params* params)
+{
+ /* No sanitization, so we should complain. */
+
+ newbuf = kvzalloc(params->buffer_size, /* { dg-warning "use of attacker-controlled value '\\*params.buffer_size' as allocation size without upper-bounds checking" "PR analyzer/112850" } */
+ (((gfp_t)(0x400u | 0x800u)) | ((gfp_t)0x40u) | ((gfp_t)0x80u)));
+ if (!newbuf)
+ return -12;
+ return 0;
+}
+
+long
+snd_rawmidi_ioctl(unsigned long arg)
+{
+ void* argp = (void*)arg;
+ struct snd_rawmidi_params params;
+ if (copy_from_user(¶ms, argp, sizeof(struct snd_rawmidi_params)))
+ return -14;
+ return resize_runtime_buffer(¶ms);
+}
--- /dev/null
+/* Reduced from false positive in Linux kernel in sound/core/rawmidi.c. */
+
+/* { dg-do compile } */
+/* { dg-options "-fanalyzer -O2 -Wanalyzer-symbol-too-complex" } */
+/* { dg-require-effective-target analyzer } */
+
+typedef unsigned long __kernel_ulong_t;
+typedef __kernel_ulong_t __kernel_size_t;
+typedef __kernel_size_t size_t;
+typedef unsigned int gfp_t;
+
+extern unsigned long copy_from_user(void* to, const void* from, unsigned long n);
+
+extern
+__attribute__((__alloc_size__(1)))
+__attribute__((__malloc__)) void*
+kvzalloc(size_t size, gfp_t flags);
+
+struct snd_rawmidi_params
+{
+ int stream;
+ size_t buffer_size;
+};
+
+char *newbuf;
+
+static int
+resize_runtime_buffer(struct snd_rawmidi_params* params)
+{
+ if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L) /* { dg-bogus "symbol too complicated" } */
+ return -22;
+ newbuf = kvzalloc(params->buffer_size, /* { dg-bogus "use of attacker-controlled value '\\*params.buffer_size' as allocation size without upper-bounds checking" "PR analyzer/112850" } */
+ (((gfp_t)(0x400u | 0x800u)) | ((gfp_t)0x40u) | ((gfp_t)0x80u)));
+ if (!newbuf)
+ return -12;
+ return 0;
+}
+
+long
+snd_rawmidi_ioctl(unsigned long arg)
+{
+ void* argp = (void*)arg;
+ struct snd_rawmidi_params params;
+ if (copy_from_user(¶ms, argp, sizeof(struct snd_rawmidi_params)))
+ return -14;
+ return resize_runtime_buffer(¶ms);
+}