-
Notifications
You must be signed in to change notification settings - Fork 29
Fix buffer overflow in CPU block_ldlt in find_maxloc on NaNs #234
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -202,7 +202,9 @@ void find_maxloc(const int from, const T *a, int lda, T &bestv_out, int &rloc, i | |
| cloc = bc2[i].i; | ||
| } | ||
| } | ||
| bestv_out = a[cloc*lda+rloc]; | ||
| bestv_out = | ||
| (cloc < BLOCK_SIZE && rloc < BLOCK_SIZE) ? a[cloc*lda+rloc] | ||
| : 0.0; | ||
| } | ||
|
|
||
| /** Returns true if a 2x2 pivot can be stably inverted. | ||
|
|
@@ -298,6 +300,9 @@ void block_ldlt(int from, int *perm, T *a, int lda, T *d, T *ldwork, | |
| int t, m; // row and col location of maximum entry | ||
| find_maxloc<T,BLOCK_SIZE>(p, a, lda, bestv, t, m); | ||
|
|
||
| // Handle case where find_maxloc failed (e.g., due to NaNs in the input) | ||
| if (t >= BLOCK_SIZE || m >= BLOCK_SIZE) throw SingularError(p); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not quite sure about this check. It unconditionally gives up with
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, if If I do not add this check, i.e., if I add only the if(pivsiz == 0) {
// FIXME: debug remove
printf("broken!\n");
…
exit(1);
}crash case. Assuming it gets so far to begin with, because
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But in my tests, the "broken!" error is what I hit without this added check. |
||
|
|
||
| // Handle case where everything remaining is small | ||
| // NB: There might be delayed columns! | ||
| if(fabs(bestv) < small) { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not understand why this can just be removed and how it relates to the other changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it safe to just remove? To be honest, I do not know. I just know that it did not crash when I removed this check, so I can only hope it did not corrupt memory somewhere.
What I do know is that if I do not remove this check, then the exception I throw with the
if (t >= BLOCK_SIZE || m >= BLOCK_SIZE) throw SingularError(p);inblock_ldlt.hxxcauses~Pageto be run in this(next_ && head_[nlevel-1] != 0)state, so it throws thatstd::runtime_error, andstd::terminategets called as a result. So something has to be done about that.If removing the check is not safe, then we need another way to handle this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might also be that existing exceptions thrown in
block_ldlt.hxxby this check:can also trigger this error case, but I am not sure about that either. It might also be that it only gets triggered because I am throwing an exception also in the case of a non-zero
action(i.e., that that is the context in which the exception is unexpected). I do not understand the allocator usage well enough yet to know the answer.