diff options
author | David Malcolm <dmalcolm@redhat.com> | 2021-02-17 17:50:52 -0500 |
---|---|---|
committer | David Malcolm <dmalcolm@redhat.com> | 2021-02-17 17:50:52 -0500 |
commit | 963aecff2473080d748b2fc1ea2e32cef36cab11 (patch) | |
tree | da6a9a3a63cb8c361dae5369b57be7536529bbe5 /gcc | |
parent | d8889c99aab4b599aa7ceb7079e69a9766171336 (diff) | |
download | gcc-963aecff2473080d748b2fc1ea2e32cef36cab11.zip gcc-963aecff2473080d748b2fc1ea2e32cef36cab11.tar.gz gcc-963aecff2473080d748b2fc1ea2e32cef36cab11.tar.bz2 |
testsuite: add regression test for PR analyzer/94596
This use-after-free false positive affected GCC 10, but seems to be
fixed in trunk for GCC 11; adding a reduced version as a regression
test.
gcc/testsuite/ChangeLog:
PR analyzer/94596
* gcc.dg/analyzer/pr94596.c: New test.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/testsuite/gcc.dg/analyzer/pr94596.c | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr94596.c b/gcc/testsuite/gcc.dg/analyzer/pr94596.c new file mode 100644 index 0000000..055d209 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr94596.c @@ -0,0 +1,97 @@ +/* Minimized/hacked up from openvswitch lib/conntrack.c, which had this license + header: */ +/* + * Copyright (c) 2015-2019 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +typedef __SIZE_TYPE__ size_t; +#define NULL ((void *)0) +#define false 0 + +#define OBJECT_OFFSETOF(OBJECT, MEMBER)\ + __builtin_offsetof(typeof(*(OBJECT)), MEMBER) + +#define OBJECT_CONTAINING(POINTER, OBJECT, MEMBER) \ + ((typeof(OBJECT)) (void *) \ + ((char *) (POINTER) - OBJECT_OFFSETOF(OBJECT, MEMBER))) + +#define ASSIGN_CONTAINER(OBJECT, POINTER, MEMBER) \ + ((OBJECT) = OBJECT_CONTAINING(POINTER, OBJECT, MEMBER), (void) 0) + +#define INIT_CONTAINER(OBJECT, POINTER, MEMBER) \ + ((OBJECT) = NULL, ASSIGN_CONTAINER(OBJECT, POINTER, MEMBER)) + +#define HMAP_FOR_EACH_POP(NODE, MEMBER, HMAP) \ + for (size_t bucket__ = 0; \ + INIT_CONTAINER(NODE, hmap_pop_helper__(HMAP, &bucket__), MEMBER), \ + (NODE != OBJECT_CONTAINING(NULL, NODE, MEMBER)) \ + || ((NODE = NULL), false);) + +struct hmap { + struct hmap_node **buckets; + struct hmap_node *one; + size_t mask; + size_t n; +}; + +struct hmap_node { + size_t hash; + struct hmap_node *next; +}; + +static inline void hmap_remove(struct hmap *, struct hmap_node *); + +struct hmap_node * +hmap_pop_helper__(struct hmap *hmap, size_t *bucket) { + + for (; *bucket <= hmap->mask; (*bucket)++) { + struct hmap_node *node = hmap->buckets[*bucket]; + + if (node) { + hmap_remove(hmap, node); + return node; + } + } + + return NULL; +} + +static inline void +hmap_remove(struct hmap *hmap, struct hmap_node *node) +{ + struct hmap_node **bucket = &hmap->buckets[node->hash & hmap->mask]; + while (*bucket != node) { + bucket = &(*bucket)->next; + } + *bucket = node->next; + hmap->n--; +} + +struct conntrack { + struct hmap zone_limits; +}; + +struct zone_limit { + struct hmap_node node; +}; + +void +conntrack_destroy(struct conntrack *ct) +{ + struct zone_limit *zl; + HMAP_FOR_EACH_POP (zl, node, &ct->zone_limits) { + __builtin_free(zl); + } +} |