diff --git a/.gitignore b/.gitignore
index 61b6f643cdeeb855e334681d1b28d9727e745e01..5337825708adc52172f18ec13b54dbdc2d4f5695 100644
--- a/.gitignore
+++ b/.gitignore
@@ -59,6 +59,7 @@ test/connector_c/update
 test/connector_c/xlog
 test/lib/*.pyc
 test/lib/*/*.pyc
+test/unit/base64
 test/unit/bit_test
 test/unit/bitset_basic_test
 test/unit/bitset_iterator_test
diff --git a/cmake/BuildMisc.cmake b/cmake/BuildMisc.cmake
index e8975a5021977408b31ff9de8445b63e513472c5..8484ee83d2565344acbc502f7a57f5196bde3884 100644
--- a/cmake/BuildMisc.cmake
+++ b/cmake/BuildMisc.cmake
@@ -6,6 +6,7 @@ macro(libmisc_build)
         ${PROJECT_SOURCE_DIR}/third_party/proctitle.c
         ${PROJECT_SOURCE_DIR}/third_party/qsort_arg.c
         ${PROJECT_SOURCE_DIR}/third_party/PMurHash.c
+        ${PROJECT_SOURCE_DIR}/third_party/base64.c
     )
 
     if (NOT HAVE_MEMMEM)
diff --git a/include/pickle.h b/include/pickle.h
index 0e35d4c9788da31d62fa6433ca3fc6f0dba48310..ff6e9297c089be3c6dad03c0f191cdad60b290b8 100644
--- a/include/pickle.h
+++ b/include/pickle.h
@@ -187,35 +187,6 @@ pick_field_u32(const void **data, const void *end)
 	return *(uint32_t *) pick_str(data, end, size);
 }
 
-
-
-static inline uint32_t
-valid_tuple(const void *data, const void *end, uint32_t field_count)
-{
-	const void *start = data;
-
-	for (int i = 0; i < field_count; i++)
-		pick_field(&data, end);
-
-	return (const char *) data - (const char *) start;
-}
-
-/**
- * Calculate size for a specified fields range
- *
- * @returns size of fields data including size of varint data
- */
-static inline size_t
-tuple_range_size(const void **begin, const void *end, size_t count)
-{
-	const void *start = *begin;
-	while (*begin < end && count-- > 0) {
-		size_t len = load_varint32(begin);
-		*begin = (char *) *begin + len;
-	}
-	return (const char *) *begin - (const char *) start;
-}
-
 static inline size_t
 varint32_sizeof(uint32_t value)
 {
diff --git a/src/box/box.cc b/src/box/box.cc
index 2cd543fe916e685b4354c7f737417ebdff260272..707c72527ee8f3aba30e5af8103f4cda8cf95dfa 100644
--- a/src/box/box.cc
+++ b/src/box/box.cc
@@ -49,6 +49,7 @@ extern "C" {
 #include "port.h"
 #include "request.h"
 #include "txn.h"
+#include <third_party/base64.h>
 
 static void process_replica(struct port *port,
 			    u32 op, const void *reqdata, u32 reqlen);
@@ -122,6 +123,27 @@ recover_snap_row(const void *data)
 
 	const struct box_snap_row *row = (const struct box_snap_row *) data;
 
+	if (valid_tuple(row->data, row->data + row->data_size,
+			row->tuple_size) != row->data_size) {
+		say_error("\n"
+			  "********************************************\n"
+		          "* Found a corrupted tuple in the snapshot! *\n"
+		          "* This can be either due to a memory       *\n"
+		          "* corruption or a bug in the server.       *\n"
+		          "* The tuple can not be loaded.             *\n"
+		          "********************************************\n"
+		          "Tuple data, BAS64 encoded:                  \n");
+
+		int base64_buflen = base64_bufsize(row->data_size);
+		char *base64_buf = (char *) malloc(base64_buflen);
+		int len = base64_encode((const char *) row->data, row->data_size,
+					base64_buf, base64_buflen);
+		write(STDERR_FILENO, base64_buf, len);
+		free(base64_buf);
+
+		tnt_raise(IllegalParams, "invalid tuple length");
+	}
+
 	struct tuple *tuple = tuple_alloc(row->data_size);
 	memcpy(tuple->data, row->data, row->data_size);
 	tuple->field_count = row->tuple_size;
diff --git a/src/box/tuple.cc b/src/box/tuple.cc
index e3e06627b70fc383350fd30788656d288935af01..2e42bf0ac0d5b68d80eac1bae67c7bfc7ab08929 100644
--- a/src/box/tuple.cc
+++ b/src/box/tuple.cc
@@ -28,7 +28,6 @@
  */
 #include "tuple.h"
 
-#include <pickle.h>
 #include <salloc.h>
 #include "tbuf.h"
 
diff --git a/src/box/tuple.h b/src/box/tuple.h
index 32f1c709d460f207a04beb1c3d8ea88b5574bc76..d3bc4c58e3d2322939f4b654febe97f7cd270499 100644
--- a/src/box/tuple.h
+++ b/src/box/tuple.h
@@ -29,6 +29,7 @@
  * SUCH DAMAGE.
  */
 #include <util.h>
+#include <pickle.h>
 
 struct tbuf;
 
@@ -93,5 +94,28 @@ static inline size_t tuple_len(struct tuple *tuple)
 }
 
 void tuple_free(struct tuple *tuple);
+
+/**
+ * Calculate size for a specified fields range
+ *
+ * @returns size of fields data including size of varint data
+ */
+static inline size_t
+tuple_range_size(const void **begin, const void *end, size_t count)
+{
+	const char *start = (const char *) *begin;
+	while (*begin < end && count-- > 0) {
+		size_t len = load_varint32(begin);
+		*begin = (const char *) *begin + len;
+	}
+	return (const char*) *begin - start;
+}
+
+static inline uint32_t
+valid_tuple(const void *data, const void *end, uint32_t field_count)
+{
+	return tuple_range_size(&data, end, field_count);
+}
+
 #endif /* TARANTOOL_BOX_TUPLE_H_INCLUDED */
 
diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt
index 20f2d55fc55d30f51f208b6f43ba785c4744ebd2..934e68d42dae60701eb64d45b6349016d578f32d 100644
--- a/test/unit/CMakeLists.txt
+++ b/test/unit/CMakeLists.txt
@@ -16,3 +16,4 @@ add_executable(bitset_iterator_test bitset_iterator.c)
 target_link_libraries(bitset_iterator_test bitset)
 add_executable(bitset_index_test bitset_index.c)
 target_link_libraries(bitset_index_test bitset)
+add_executable(base64 base64.c ${CMAKE_SOURCE_DIR}/third_party/base64.c)
diff --git a/test/unit/base64.c b/test/unit/base64.c
new file mode 100644
index 0000000000000000000000000000000000000000..dca11da881db7b082e8e25aa444514984cf65bdc
--- /dev/null
+++ b/test/unit/base64.c
@@ -0,0 +1,40 @@
+#include <third_party/base64.h>
+#include "unit.h"
+#include <string.h>
+
+
+static void
+base64_test(const char *str)
+{
+	header();
+
+	int len = strlen(str);
+	int base64_buflen = len * 4/3 + 4;
+	char *base64_buf = malloc(base64_buflen);
+	char *strbuf = malloc(len + 1);
+
+	int res = base64_encode(str, len, base64_buf, base64_buflen);
+
+	fail_unless(strlen(base64_buf) == res);
+
+	base64_decode(base64_buf, strlen(base64_buf), strbuf, len + 1);
+
+	fail_unless(strcmp(str, strbuf) == 0);
+
+	free(base64_buf);
+	free(strbuf);
+
+	footer();
+}
+
+int main(int argc, char *argv[])
+{
+	base64_test("");
+	base64_test("a");
+	base64_test("Something that doesn't fit into a single line, "
+	            "something that doesn't fit into a single line, "
+	            "something that doesn't fit into a single line, "
+	            "something that doesn't fit into a single line, "
+	            "something that doesn't fit into a single line. ");
+	base64_test("\001\002\003\004\005\006\253\254\255");
+}
diff --git a/test/unit/base64.result b/test/unit/base64.result
new file mode 100644
index 0000000000000000000000000000000000000000..de91f62a78d9d1b119ae8bcb05e460ef21e867a8
--- /dev/null
+++ b/test/unit/base64.result
@@ -0,0 +1,9 @@
+	*** base64_test ***
+	*** base64_test: done ***
+ 	*** base64_test ***
+	*** base64_test: done ***
+ 	*** base64_test ***
+	*** base64_test: done ***
+ 	*** base64_test ***
+	*** base64_test: done ***
+ 
\ No newline at end of file
diff --git a/test/unit/base64.test b/test/unit/base64.test
new file mode 100644
index 0000000000000000000000000000000000000000..0ed8d1b67d7103560b29ab48c9c8becec98619b8
--- /dev/null
+++ b/test/unit/base64.test
@@ -0,0 +1 @@
+run_test("base64")
diff --git a/test/unit/unit.h b/test/unit/unit.h
index add8a8e33439c8d2ffa9bfd005980f4c00d442c1..4ab24ea935bb68e71501c21a0e111b734dd9757c 100644
--- a/test/unit/unit.h
+++ b/test/unit/unit.h
@@ -30,6 +30,7 @@
  */
 #include <unistd.h>
 #include <stdlib.h> /* exit() */
+#include <stdio.h>
 
 #define header() printf("\t*** %s ***\n", __func__)
 #define footer() printf("\t*** %s: done ***\n ", __func__)
diff --git a/third_party/base64.c b/third_party/base64.c
new file mode 100644
index 0000000000000000000000000000000000000000..5ec20929050f6101012f2c736864f00ef15e3491
--- /dev/null
+++ b/third_party/base64.c
@@ -0,0 +1,296 @@
+/*
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the
+ *    following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "third_party/base64.h"
+/*
+ * This is part of the libb64 project, and has been placed in the
+ * public domain. For details, see
+ * http://sourceforge.net/projects/libb64
+ */
+
+
+/* {{{ encode */
+
+enum base64_encodestep { step_A, step_B, step_C };
+
+struct base64_encodestate {
+	enum base64_encodestep step;
+	char result;
+	int stepcount;
+};
+
+static inline void
+base64_encodestate_init(struct base64_encodestate *state)
+{
+	state->step = step_A;
+	state->result = 0;
+	state->stepcount = 0;
+}
+
+static inline char
+base64_encode_value(char value)
+{
+	static const char encoding[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+	unsigned codepos = (unsigned) value;
+	if (codepos > sizeof(encoding) - 1)
+		return '=';
+	return encoding[codepos];
+}
+
+static int
+base64_encode_block(const char *in_bin, int in_len,
+		    char *out_base64, int out_len,
+		    struct base64_encodestate *state)
+{
+	const char *const in_end = in_bin + in_len;
+	const char *in_pos = in_bin;
+	char *out_pos = out_base64;
+	char *out_end = out_base64  + out_len;
+	char result;
+	char fragment;
+
+	result = state->result;
+
+	switch (state->step)
+	{
+		while (1)
+		{
+	case step_A:
+			if (in_pos == in_end || out_pos >= out_end) {
+				state->result = result;
+				state->step = step_A;
+				return out_pos - out_base64;
+			}
+			fragment = *in_pos++;
+			result = (fragment & 0x0fc) >> 2;
+			*out_pos++ = base64_encode_value(result);
+			result = (fragment & 0x003) << 4;
+	case step_B:
+			if (in_pos == in_end || out_pos >= out_end) {
+				state->result = result;
+				state->step = step_B;
+				return out_pos - out_base64;
+			}
+			fragment = *in_pos++;
+			result |= (fragment & 0x0f0) >> 4;
+			*out_pos++ = base64_encode_value(result);
+			result = (fragment & 0x00f) << 2;
+	case step_C:
+			if (in_pos == in_end || out_pos + 2 >= out_end) {
+				state->result = result;
+				state->step = step_C;
+				return out_pos - out_base64;
+			}
+			fragment = *in_pos++;
+			result |= (fragment & 0x0c0) >> 6;
+			*out_pos++ = base64_encode_value(result);
+			result  = (fragment & 0x03f) >> 0;
+			*out_pos++ = base64_encode_value(result);
+
+			/*
+			 * Each full step (A->B->C) yields
+			 * 4 characters.
+			 */
+			if (++state->stepcount * 4 == BASE64_CHARS_PER_LINE) {
+				if (out_pos >= out_end)
+					return out_pos - out_base64;
+				*out_pos++ = '\n';
+				state->stepcount = 0;
+			}
+		}
+	}
+	/* control should not reach here */
+	return out_pos - out_base64;
+}
+
+static int
+base64_encode_blockend(char *out_base64, int out_len,
+		       struct base64_encodestate *state)
+{
+	char *out_pos = out_base64;
+	char *out_end = out_base64 + out_len;
+
+	switch (state->step) {
+	case step_B:
+		if (out_pos + 2 >= out_end)
+			return out_pos - out_base64;
+		*out_pos++ = base64_encode_value(state->result);
+		*out_pos++ = '=';
+		*out_pos++ = '=';
+		break;
+	case step_C:
+		if (out_pos + 1 >= out_end)
+			return out_pos - out_base64;
+		*out_pos++ = base64_encode_value(state->result);
+		*out_pos++ = '=';
+		break;
+	case step_A:
+		break;
+	}
+	if (out_pos >= out_end)
+		return out_pos - out_base64;
+	*out_pos++ = '\n';
+	if (out_pos >= out_end)
+		return out_pos - out_base64;
+	*out_pos = '\0';
+	return out_pos - out_base64;
+}
+
+int
+base64_encode(const char *in_bin, int in_len,
+	      char *out_base64, int out_len)
+{
+	struct base64_encodestate state;
+	base64_encodestate_init(&state);
+	int res = base64_encode_block(in_bin, in_len, out_base64,
+				      out_len, &state);
+	return res + base64_encode_blockend(out_base64 + res, out_len - res,
+					    &state);
+}
+
+/* }}} */
+
+/* {{{ decode */
+
+enum base64_decodestep { step_a, step_b, step_c, step_d };
+
+struct base64_decodestate
+{
+	enum base64_decodestep step;
+	char result;
+};
+
+static char
+base64_decode_value(char value)
+{
+	static const char decoding[] = {
+		62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58,
+		59, 60, 61, -1, -1, -1, -2, -1, -1, -1,  0,  1,
+		2,   3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13,
+		14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+		-1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31,
+		32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+		44, 45, 46, 47, 48, 49, 50, 51
+	};
+	static const char decoding_size = sizeof(decoding);
+	int codepos = (signed char) value;
+	codepos -= 43;
+	if (codepos < 0 || codepos > decoding_size)
+		return -1;
+	return decoding[codepos];
+}
+
+static inline void
+base64_decodestate_init(struct base64_decodestate *state)
+{
+	state->step = step_a;
+	state->result = 0;
+}
+
+static int
+base64_decode_block(const char *in_base64, int in_len,
+		    char *out_bin, int out_len,
+		    struct base64_decodestate *state)
+{
+	const char *in_pos = in_base64;
+	const char *in_end = in_base64 + in_len;
+	char *out_pos = out_bin;
+	char *out_end = out_bin + out_len;
+	char fragment;
+
+	*out_pos = state->result;
+
+	switch (state->step)
+	{
+		while (1)
+		{
+	case step_a:
+			do {
+				if (in_pos == in_end || out_pos >= out_end)
+				{
+					state->step = step_a;
+					state->result = *out_pos;
+					return out_pos - out_bin;
+				}
+				fragment = base64_decode_value(*in_pos++);
+			} while (fragment < 0);
+			*out_pos    = (fragment & 0x03f) << 2;
+	case step_b:
+			do {
+				if (in_pos == in_end || out_pos + 1 >= out_end)
+				{
+					state->step = step_b;
+					state->result = *out_pos;
+					return out_pos - out_bin;
+				}
+				fragment = base64_decode_value(*in_pos++);
+			} while (fragment < 0);
+			*out_pos++ |= (fragment & 0x030) >> 4;
+			*out_pos    = (fragment & 0x00f) << 4;
+	case step_c:
+			do {
+				if (in_pos == in_end || out_pos + 1 >= out_end)
+				{
+					state->step = step_c;
+					state->result = *out_pos;
+					return out_pos - out_bin;
+				}
+				fragment = base64_decode_value(*in_pos++);
+			} while (fragment < 0);
+			*out_pos++ |= (fragment & 0x03c) >> 2;
+			*out_pos    = (fragment & 0x003) << 6;
+	case step_d:
+			do {
+				if (in_pos == in_end || out_pos >= out_end)
+				{
+					state->step = step_d;
+					state->result = *out_pos;
+					return out_pos - out_bin;
+				}
+				fragment = base64_decode_value(*in_pos++);
+			} while (fragment < 0);
+			*out_pos++   |= (fragment & 0x03f);
+		}
+	}
+	/* control should not reach here */
+	return out_pos - out_bin;
+}
+
+
+
+int
+base64_decode(const char *in_base64, int in_len,
+	      char *out_bin, int out_len)
+{
+	struct base64_decodestate state;
+	base64_decodestate_init(&state);
+	return base64_decode_block(in_base64, in_len,
+				   out_bin, out_len, &state);
+}
+
+/* }}} */
diff --git a/third_party/base64.h b/third_party/base64.h
new file mode 100644
index 0000000000000000000000000000000000000000..d590820ddb775f816cce7ef9941d47cd8cd70890
--- /dev/null
+++ b/third_party/base64.h
@@ -0,0 +1,91 @@
+#ifndef BASE64_H
+#define BASE64_H
+/*
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the
+ *    following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * This is part of the libb64 project, and has been placed in the
+ * public domain. For details, see
+ * http://sourceforge.net/projects/libb64
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define BASE64_CHARS_PER_LINE 72
+
+static inline int
+base64_bufsize(int binsize)
+{
+	int datasize = binsize * 4/3 + 4;
+	int newlines = ((datasize + BASE64_CHARS_PER_LINE - 1)/
+			BASE64_CHARS_PER_LINE);
+	return datasize + newlines;
+}
+
+/**
+ * Encode a binary stream into BASE64 text.
+ *
+ * @pre the buffer size is at least 4/3 of the stream
+ * size + stream_size/72 (newlines) + 4
+ *
+ * @param[in]  in_bin           the binary input stream to decode
+ * @param[in]  in_len		size of the input
+ * @param[out] out_base64       output buffer for the encoded data
+ * @param[in]  out_len          buffer size, must be at least
+ *				4/3 of the input size
+ *
+ * @return the size of encoded output
+ */
+
+int
+base64_encode(const char *in_bin, int in_len,
+	      char *out_base64, int out_len);
+
+/**
+ * Decode a BASE64 text into a binary
+ *
+ * @param[in]  in_base64	the BASE64 stream to decode
+ * @param[in]  in_len		size of the input
+ * @param[out] out_bin		output buffer size
+ * @param[in]  out_len		buffer size
+ *
+ * @pre the output buffer size must be at least
+ * 3/4 + 1 of the size of the input
+ *
+ * @return the size of decoded output
+ */
+
+int base64_decode(const char *in_base64, int in_len,
+		  char *out_bin, int out_len);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+#endif /* BASE64_H */
+