diff -Naur libotr-3.2.0/src/b64.c libotr-3.2.0.new/src/b64.c
--- libotr-3.2.0/src/b64.c	2008-05-27 15:35:28.000000000 +0200
+++ libotr-3.2.0.new/src/b64.c	2014-02-02 01:42:31.056704600 +0100
@@ -55,7 +55,7 @@
 \******************************************************************* */
 
 /* system headers */
-#include <stdlib.h>
+#include <stdio.h>
 #include <string.h>
 
 /* libotr headers */
@@ -147,8 +147,9 @@
  * base64 decode data.  Skip non-base64 chars, and terminate at the
  * first '=', or the end of the buffer.
  *
- * The buffer data must contain at least (base64len / 4) * 3 bytes of
- * space.  This function will return the number of bytes actually used.
+ * The buffer data must contain at least ((base64len+3) / 4) * 3 bytes
+ * of space.  This function will return the number of bytes actually
+ * used.
  */
 size_t otrl_base64_decode(unsigned char *data, const char *base64data,
 	size_t base64len)
@@ -234,13 +235,18 @@
 	return -2;
     }
 
+    /* Skip over the "?OTR:" */
+    otrtag += 5;
+    msglen -= 5;
+
     /* Base64-decode the message */
-    rawlen = ((msglen-5) / 4) * 3;   /* maximum possible */
+    rawlen = OTRL_B64_MAX_DECODED_SIZE(msglen);   /* maximum possible */
     rawmsg = malloc(rawlen);
     if (!rawmsg && rawlen > 0) {
 	return -1;
     }
-    rawlen = otrl_base64_decode(rawmsg, otrtag+5, msglen-5);  /* actual size */
+
+    rawlen = otrl_base64_decode(rawmsg, otrtag, msglen);  /* actual size */
 
     *bufp = rawmsg;
     *lenp = rawlen;
diff -Naur libotr-3.2.0/src/b64.h libotr-3.2.0.new/src/b64.h
--- libotr-3.2.0/src/b64.h	2008-05-27 15:35:28.000000000 +0200
+++ libotr-3.2.0.new/src/b64.h	2014-02-02 01:42:31.078705900 +0100
@@ -20,6 +20,19 @@
 #ifndef __B64_H__
 #define __B64_H__
 
+#include <stdlib.h>
+
+/* Base64 encodes blocks of this many bytes: */
+#define OTRL_B64_DECODED_LEN 3
+/* into blocks of this many bytes: */
+#define OTRL_B64_ENCODED_LEN 4
+
+/* An encoded block of length encoded_len can turn into a maximum of
+ * this many decoded bytes: */
+#define OTRL_B64_MAX_DECODED_SIZE(encoded_len) \
+    (((encoded_len + OTRL_B64_ENCODED_LEN - 1) / OTRL_B64_ENCODED_LEN) \
+	* OTRL_B64_DECODED_LEN)
+
 /*
  * base64 encode data.  Insert no linebreaks or whitespace.
  *
@@ -33,8 +46,9 @@
  * base64 decode data.  Skip non-base64 chars, and terminate at the
  * first '=', or the end of the buffer.
  *
- * The buffer data must contain at least (base64len / 4) * 3 bytes of
- * space.  This function will return the number of bytes actually used.
+ * The buffer data must contain at least ((base64len+3) / 4) * 3 bytes
+ * of space.  This function will return the number of bytes actually
+ * used.
  */
 size_t otrl_base64_decode(unsigned char *data, const char *base64data,
 	size_t base64len);
diff -Naur libotr-3.2.0/src/proto.c libotr-3.2.0.new/src/proto.c
--- libotr-3.2.0/src/proto.c	2008-05-27 15:35:28.000000000 +0200
+++ libotr-3.2.0.new/src/proto.c	2014-02-02 01:42:31.004701700 +0100
@@ -537,13 +537,17 @@
 	msglen = strlen(otrtag);
     }
 
+    /* Skip over the "?OTR:" */
+    otrtag += 5;
+    msglen -= 5;
+
     /* Base64-decode the message */
-    rawlen = ((msglen-5) / 4) * 3;   /* maximum possible */
+    rawlen = OTRL_B64_MAX_DECODED_SIZE(msglen);   /* maximum possible */
     rawmsg = malloc(rawlen);
     if (!rawmsg && rawlen > 0) {
 	return gcry_error(GPG_ERR_ENOMEM);
     }
-    rawlen = otrl_base64_decode(rawmsg, otrtag+5, msglen-5);  /* actual size */
+    rawlen = otrl_base64_decode(rawmsg, otrtag, msglen);  /* actual size */
 
     bufp = rawmsg;
     lenp = rawlen;
@@ -606,14 +610,18 @@
 	msglen = strlen(otrtag);
     }
 
+    /* Skip over the "?OTR:" */
+    otrtag += 5;
+    msglen -= 5;
+
     /* Base64-decode the message */
-    rawlen = ((msglen-5) / 4) * 3;   /* maximum possible */
+    rawlen = OTRL_B64_MAX_DECODED_SIZE(msglen);   /* maximum possible */
     rawmsg = malloc(rawlen);
     if (!rawmsg && rawlen > 0) {
 	err = gcry_error(GPG_ERR_ENOMEM);
 	goto err;
     }
-    rawlen = otrl_base64_decode(rawmsg, otrtag+5, msglen-5);  /* actual size */
+    rawlen = otrl_base64_decode(rawmsg, otrtag, msglen);  /* actual size */
 
     bufp = rawmsg;
     lenp = rawlen;
diff -Naur libotr-3.2.0/toolkit/parse.c libotr-3.2.0.new/toolkit/parse.c
--- libotr-3.2.0/toolkit/parse.c	2008-05-27 15:35:28.000000000 +0200
+++ libotr-3.2.0.new/toolkit/parse.c	2014-02-02 01:42:30.990700900 +0100
@@ -64,7 +64,8 @@
 {
     const char *header, *footer;
     unsigned char *raw;
-	
+    size_t rawlen;
+
     /* Find the header */
     header = strstr(msg, "?OTR:");
     if (!header) return NULL;
@@ -75,8 +76,10 @@
     footer = strchr(header, '.');
     if (!footer) footer = header + strlen(header);
 
-    raw = malloc((footer-header) / 4 * 3);
-    if (raw == NULL && (footer-header >= 4)) return NULL;
+    rawlen = OTRL_B64_MAX_DECODED_SIZE(footer-header);
+
+    raw = malloc(rawlen);
+    if (raw == NULL && rawlen > 0) return NULL;
     *lenp = otrl_base64_decode(raw, header, footer-header);
 
     return raw;
