Skip to content

Fix patch crash#945

Merged
implausible merged 3 commits into
masterfrom
fix-patch-crash
Mar 9, 2016
Merged

Fix patch crash#945
implausible merged 3 commits into
masterfrom
fix-patch-crash

Conversation

@joshaber

@joshaber joshaber commented Mar 9, 2016

Copy link
Copy Markdown
Collaborator

Libgit2 documents that content isn’t NUL-terminated, so we can’t
call strlen on it. If we do, we’ll probably crash.

joshaber added 2 commits March 9, 2016 10:39
Libgit2 documents that the content isn’t NUL-terminated, so we can’t
call strlen on it.
}

if (j == 0) {
// calculate strlen only once for the first line of the first hunk.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment doesn't really describe what we were doing, and I'm not sure I understand what we're trying to do. So I'm not sure if this comment was wrong, or the code is wrong 😅

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment means that we don't want to calculate the length of content every iteration of the loop because that is numLinesInContent * strlen iterations. This slows down performance substantially.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess my confusion is that (1) it's not like we were re-using the length, and (2) we're doing this for the first line of every hunk, not just the first line of the first hunk as the comment says.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the way that libgit2 represents the content pointer is like this:
Content ptr points to the start of the first line in the hunk, but continues until the end of the file.
content_len is the length of the line that we are looking at in the hunk
\n\ No newline at end of file\n" is located at the end of content ptr (not at content_len).
content ptr continues to the last line of the file because content ptr does not terminate at the end of lines.

What we need to know at any given line is whether there is no new line at the end of the file as this is used in nodegit for staging. When I worked on this feature it was requested that we preserve the api as closely as possible. The best way to preserve the api was to append the no new line flag on the end of lines where we have discovered a file does not contain a new line at the end.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to investigate what a diff line looks like before we finalize this.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, you're right to be a bit confused. lol.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the comment is completely wrong.

@joshaber

joshaber commented Mar 9, 2016

Copy link
Copy Markdown
Collaborator Author

This fixes a crash we saw in Atom. The crashlog would look like this:

Exception Type:        EXC_BAD_ACCESS (SIGSEGV)
Exception Codes:       KERN_INVALID_ADDRESS at 0x0000000125f72000

...

Thread 14 Crashed:
0   libsystem_c.dylib               0x00007fff863db188 strlen + 72
1   nodegit.node                    0x00000001164ef072 createFromRaw(git_patch*) + 525
2   nodegit.node                    0x00000001165b7069 GitPatch::ConvenientFromDiffWorker::Execute() + 153
3   libnode.dylib                   0x0000000110c4c48e 0x110b08000 + 1328270
4   libnode.dylib                   0x0000000110c4c68b 0x110b08000 + 1328779
5   libnode.dylib                   0x0000000110c57189 0x110b08000 + 1372553
6   libsystem_pthread.dylib         0x00007fff968e9c13 _pthread_body + 131
7   libsystem_pthread.dylib         0x00007fff968e9b90 _pthread_start + 168
8   libsystem_pthread.dylib         0x00007fff968e7375 thread_start + 13

@joshaber

joshaber commented Mar 9, 2016

Copy link
Copy Markdown
Collaborator Author

This is ready 🙏

@johnhaley81

Copy link
Copy Markdown
Collaborator

@implausible could you also 👀 this?

@implausible

Copy link
Copy Markdown
Member

This looks good to me 👍. I don't even know how I got to this solution anymore. So huge thanks to Josh for fixing yet another one of my errors. ❤️

implausible added a commit that referenced this pull request Mar 9, 2016
@implausible implausible merged commit bb9d785 into master Mar 9, 2016
@johnhaley81 johnhaley81 deleted the fix-patch-crash branch March 9, 2016 17:12
@implausible

Copy link
Copy Markdown
Member

@joshaber took a quick walk. I think I understand where I got this wrong now. The no new line flag only matters for the last hunk in the diff. I assumed it was required for every line of every hunk. This is wrong. Thanks again!

@joshaber

joshaber commented Mar 9, 2016

Copy link
Copy Markdown
Collaborator Author

Ah, I see. Thanks for clarifying @implausible!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants