[OTR-dev] Crash when receiving message after canceling encrypted chat (with gdb backtrace)
Ian Goldberg
ian at cypherpunks.ca
Wed Feb 9 17:53:26 EST 2005
On Wed, Feb 09, 2005 at 04:15:21PM -0600, Evan Schoenberg wrote:
> Here's a normal output with my logging. (The second set of information
> in lines 2 through 4 is the pointer as output by %x).
> otrl_proto_create_data: starting with context->lastmessage:
> "[resent] <HTML>Message sent while secure</HTML>" msg: "<HTML>Another
> message sent while secure</HTML>"
> otrl_proto_create_data: will do strcpy("", "[resent] "), which is
> strcpy(70ed248, 68596c4)
> otrl_proto_create_data: will do strcat("[resent] ", "<HTML>Another
> message sent while secure</HTML>"), which is strcat(70ed248, 634ce90)
> otrl_proto_create_data: SUCCESS: generated [resent] <HTML>Another
> message sent while secure</HTML> (70ed248)
>
> Here's the crash:
> otrl_proto_create_data: starting with context->lastmessage:
> "[resent] <HTML>Another message sent while secure</HTML>" msg: "<HTML>Now,
> a message sent after being notified the other side is no longer using
> encryption</HTML>"
> otrl_proto_create_data: will do strcpy("", "[resent] "), which is
> strcpy(70f3e88, 68596c4)
> otrl_proto_create_data: will do strcat("[resent] ", "<HTML>Now, a
> message sent after being notified the other side is no longer using
> encryption</HTML>"), which is strcat(70f3e88, 70f03e0)
> otrl_proto_create_data: SUCCESS: generated [resent] <HTML>Now, a
> message sent after being notified the other side is no longer using
> encryption</HTML> (70f3e88)
> otrl_proto_create_data: starting with context->lastmessage:
> "[resent] <HTML>Now, a message sent after being notified the other side is
> no longer using encryption</HTML>", "[resent] <HTML>Now, a message sent
> after being notified the other side is no longer using
> encryption</HTML>"
> otrl_proto_create_data: will do strcpy("", "[resent] "), which is
> strcpy(70f3e88, 68596c4)
> otrl_proto_create_data: will do strcat("[resent] ", msg: "[resent]
> "), which is strcat(70f3e88, 70f3e88)
> *** malloc[19494]: error for object 0x70f1db0: Double free
> <CRASH>
>
> Two interesting things I notice here... First, that method is getting
> called twice; presumably the second time is after encryption is
> re-established. Second, the second call attempts to do strcat(x, x),
> which crashes.
I was writing to say how impossible this trace is, when this old
aphorism came to mind: "Those saying something is impossible
should never interrupt those who are doing it."
Please apply this patch and tell me if the problem goes away.
Thanks,
- Ian
diff -u -r1.10 proto.c
--- proto.c 7 Feb 2005 20:34:50 -0000 1.10
+++ proto.c 9 Feb 2005 22:46:31 -0000
@@ -735,6 +735,14 @@
char *msgbuf = NULL;
enum gcry_mpi_format format = GCRYMPI_FMT_USG;
+ /* We need to copy the incoming msg, since it might be an alias for
+ * context->lastmessage, which we'll be freeing soon. */
+ char *msgdup = gcry_malloc_secure(justmsglen + 1);
+ if (msgdup == NULL) {
+ return gcry_error(GPG_ERR_ENOMEM);
+ }
+ strcpy(msgdup, msg);
+
*encmessagep = NULL;
/* Header, send keyid, recv keyid, counter, msg len, msg
@@ -746,10 +754,11 @@
msgbuf = gcry_malloc_secure(msglen);
if (buf == NULL || msgbuf == NULL) {
free(buf);
- free(msgbuf);
+ gcry_free(msgbuf);
+ gcry_free(msgdup);
return gcry_error(GPG_ERR_ENOMEM);
}
- memmove(msgbuf, msg, justmsglen);
+ memmove(msgbuf, msgdup, justmsglen);
msgbuf[justmsglen] = '\0';
otrl_tlv_serialize(msgbuf + justmsglen + 1, tlvs);
bufp = buf;
@@ -824,7 +833,7 @@
if (msglen > 0) {
const char *prefix = "[resent] ";
size_t prefixlen = strlen(prefix);
- if (!strncmp(prefix, msg, prefixlen)) {
+ if (!strncmp(prefix, msgdup, prefixlen)) {
/* The prefix is already there. Don't add it again. */
prefix = "";
prefixlen = 0;
@@ -832,13 +841,15 @@
context->lastmessage = gcry_malloc_secure(prefixlen + justmsglen + 1);
if (context->lastmessage) {
strcpy(context->lastmessage, prefix);
- strcat(context->lastmessage, msg);
+ strcat(context->lastmessage, msgdup);
}
}
+ gcry_free(msgdup);
return gcry_error(GPG_ERR_NO_ERROR);
err:
free(buf);
gcry_free(msgbuf);
+ gcry_free(msgdup);
*encmessagep = NULL;
return err;
}
More information about the OTR-dev
mailing list