Open Quuxplusone opened 5 years ago
Bugzilla Link | PR40913 |
Status | CONFIRMED |
Importance | P normal |
Reported by | Leslie Zhai (zhaixiang@loongson.cn) |
Reported on | 2019-02-28 17:48:37 -0800 |
Last modified on | 2020-09-19 07:24:42 -0700 |
Version | trunk |
Hardware | Other Linux |
CC | dcoughlin@apple.com, lebedev.ri@gmail.com, llvm-bugs@lists.llvm.org, noqnoqneo@gmail.com |
Fixed by commit(s) | |
Attachments | |
Blocks | |
Blocked by | |
See also |
You may want to produce more smaller, fine-grained, self-contained reproducer,
that is not "build jdk and then analyse it".
Whoops, wrong revision :D
Anyway, i'm looking into this.
Hmm, so, even though it's not obvious, the Analyzer is in fact referring to the following execution path:
static void check_and_push(context_type context, const void ptr, int kind) { // ... // Taking true branch. if (context->alloc_stack_top < 16) p = &(context->alloc_stack[context->alloc_stack_top++]); // ... context->allocated_memory = p; }
This causes context->allocated_memory
to effectively become equal to context + N
, where N is a simple offset.
In this case when you then do free(context->allocated_memory), it either causes undefined behavior or releases the malloc()ed memory that's aliased with context
. In both cases, the bug report is valid.
The problem here is that we've "pruned" the execution path within check_and_push(), i.e. we don't display it to the user because we don't realize that there's something interesting in it. In this case the pruned path is 10 pieces long and the unpruned path is 29 pieces long. Given that we have no really good solution for figuring out if the path is interesting, should we disable pruning when unpruned path is short enough?
@Leslie Zhai, does this make sense to you? Our notes are bad, but do you think that the execution path that the Static Analyzer is complaining about is actually feasible and exposes a bug in OpenJDK?
In any case, the over-eager path pruning deserves a bug report.
Hi Roman,
Sorry for my late response!
I tried to write a reduced testcase to reproduce the bug, but failed to
reproduce...
I often use[1] huge and real OSS to analysis. It is able to find the bugs in
analyzer side and testcase side.
Hi Artem,
Long time no see :)
> In this case when you then do free(context->allocated_memory), it either
causes undefined behavior or releases the malloc()ed memory that's aliased with
`context`. In both cases, the bug report is valid.
I need to check the latest OpenJDK source code carefully, if there is UB or
other issue, I will file a bug in JBS[4].
> The problem here is that we've "pruned" the execution path within
check_and_push(), i.e. we don't display it to the user because we don't realize
that there's something interesting in it.
Yes, there is no check_and_push (be pruned) in the report[2][3].
Cheers,
Leslie Zhai
[1] https://www.leetcode.cn/2016/11/analyzing-code-for-kde-qt-open-source-
components.html
[2] https://raw.githubusercontent.com/xiangzhai/jdk-dev/master/check_code01.png
[3] https://raw.githubusercontent.com/xiangzhai/jdk-dev/master/check_code02.png
[4] https://bugs.openjdk.java.net/browse/JDK-8219074
Hi Artem,
How is going?
exposes a bug in OpenJDK?
But I have no idea how to reproduce the Use-after-free:
diff -r bdc20ee1a68d src/java.base/share/native/libverify/check_code.c
--- a/src/java.base/share/native/libverify/check_code.c Fri Sep 04 23:51:26 2020 -0400
+++ b/src/java.base/share/native/libverify/check_code.c Sat Sep 19 22:21:00 2020 +0800
@@ -1310,6 +1310,7 @@
is_internal = methodname[0] == '<';
pop_and_free(context);
+ assert(context != NULL);
clazz_info = cp_index_to_class_fullinfo(context, key,
JVM_CONSTANT_Methodref);
this_idata->operand.i = key;
Thanks, Leslie Zhai