diff --git a/.gitignore b/.gitignore
index 97d442eb02d69fc8d40e8a5da3fd7da7ac00f513..3a8eab22df6b6117a4ffb0f327cf0299dc61b5a4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,6 +22,7 @@ test/connector_c/update
 test/connector_c/snap
 test/box/protocol
 test/box/connector
+test/unit/base64
 test/unit/queue
 test/unit/mhash
 test/unit/objc_finally
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 8f3e6340a10314bf9f5bc1eb52bae081ea8cadbf..3aed167642faf75ebdfd8030449d7d61159de72a 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 data - 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 += len;
-	}
-	return *begin - start;
-}
-
 static inline size_t
 varint32_sizeof(uint32_t value)
 {
diff --git a/src/box/box.m b/src/box/box.m
index dddce327c6062ad532c2aa5bd6dc718c8c39ebac..50a2a0a878776564f8f91fc01cfe41987da23691 100644
--- a/src/box/box.m
+++ b/src/box/box.m
@@ -47,6 +47,7 @@
 #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);
@@ -250,6 +251,27 @@ recover_snap_row(const void *data)
 
 	const struct box_snap_row *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.h b/src/box/tuple.h
index 32f1c709d460f207a04beb1c3d8ea88b5574bc76..a9c215e9ac7ba629c9af8495cdecf4caef2c143b 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 void *start = *begin;
+	while (*begin < end && count-- > 0) {
+		size_t len = load_varint32(begin);
+		*begin += len;
+	}
+	return *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/src/box/tuple.m b/src/box/tuple.m
index 4c939f0dac38adfd145dce3a8c27df18883847f4..fc029099d7a6c3a4f2091e960352dc8f6fbc6ef5 100644
--- a/src/box/tuple.m
+++ b/src/box/tuple.m
@@ -28,7 +28,6 @@
  */
 #include "tuple.h"
 
-#include <pickle.h>
 #include <salloc.h>
 #include "tbuf.h"
 
diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt
index 982a932569cd0c8fb395dc2bd97d74c336c9b395..beb7c8fac63018ba5a4c505ffdb2da9353a4d4f9 100644
--- a/test/unit/CMakeLists.txt
+++ b/test/unit/CMakeLists.txt
@@ -29,3 +29,5 @@ target_link_libraries(objc_catchcxx ${LIBOBJC_LIBRARIES} ${LUAJIT_LIB} -lm -pthr
 if (TARGET_OS_LINUX OR TARGET_OS_DEBIAN_FREEBSD)
     target_link_libraries(objc_catchcxx dl)
 endif()
+
+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..c28ce6afba8a21278d23f9142339b3e9497c93df
--- /dev/null
+++ b/third_party/base64.h
@@ -0,0 +1,85 @@
+#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
+ */
+
+#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);
+
+#endif /* BASE64_H */
+