CVE-2020-26759: Buffer Copy without Checking Size of Input ('Classic Buffer Overflow') (CWE-120)
value: clickhouse-driver before 0.1.5 allows a malicious clickhouse server to trigger a crash or execute arbitrary code (on a database client) via a crafted server response, due to a buffer overflow.
CWE description: The product copies an input buffer to an output buffer without verifying that the size of the input buffer is less than the size of the output buffer, leading to a buffer overflow.
CVSS v3 base score: 9.8
Published: 2021-01-06T13:15Z
Repository: https://github.com/mymarilyn/clickhouse-driver
Language: Python
Files changed: clickhouse_driver/varint.c, clickhouse_driver/varint.pyx, tests/test_varint.py
Commit date: 2020-09-11 18:02:04 +0300
Commit message: Fix read_varint overflow

Diff: diff --git a/clickhouse_driver/varint.c b/clickhouse_driver/varint.c
index ea0f9b1..4645121 100644
--- a/clickhouse_driver/varint.c
+++ b/clickhouse_driver/varint.c
@@ -1062,12 +1062,15 @@ static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object);
 
 /* AddTraceback.proto */
 static void __Pyx_AddTraceback(const char *funcname, int c_line,
                                int py_line, const char *filename);
 
+/* CIntToPy.proto */
+static CYTHON_INLINE PyObject* __Pyx_PyInt_From_unsigned_PY_LONG_LONG(unsigned PY_LONG_LONG value);
+
 /* CIntFromPy.proto */
-static CYTHON_INLINE unsigned char __Pyx_PyInt_As_unsigned_char(PyObject *);
+static CYTHON_INLINE unsigned PY_LONG_LONG __Pyx_PyInt_As_unsigned_PY_LONG_LONG(PyObject *);
 
 /* CIntToPy.proto */
 static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value);
 
 /* CIntFromPy.proto */
@@ -1194,12 +1197,12 @@ static const char __pyx_k_test[] = "__test__";
 static const char __pyx_k_shift[] = "shift";
 static const char __pyx_k_write[] = "write";
 static const char __pyx_k_number[] = "number";
 static const char __pyx_k_result[] = "result";
 static const char __pyx_k_num_buf[] = "num_buf";
-static const char __pyx_k_towrite[] = "towrite";
 static const char __pyx_k_read_one[] = "read_one";
+static const char __pyx_k_to_write[] = "to_write";
 static const char __pyx_k_read_varint[] = "read_varint";
 static const char __pyx_k_write_varint[] = "write_varint";
 static const char __pyx_k_cline_in_traceback[] = "cline_in_traceback";
 static const char __pyx_k_clickhouse_driver_varint[] = "clickhouse_driver.varint";
 static const char __pyx_k_clickhouse_driver_varint_pyx[] = "clickhouse_driver/varint.pyx";
@@ -1216,35 +1219,35 @@ static PyObject *__pyx_n_s_number;
 static PyObject *__pyx_n_s_read_one;
 static PyObject *__pyx_n_s_read_varint;
 static PyObject *__pyx_n_s_result;
 static PyObject *__pyx_n_s_shift;
 static PyObject *__pyx_n_s_test;
-static PyObject *__pyx_n_s_towrite;
+static PyObject *__pyx_n_s_to_write;
 static PyObject *__pyx_n_s_write;
 static PyObject *__pyx_n_s_write_varint;
-static PyObject *__pyx_pf_17clickhouse_driver_6varint_write_varint(CYTHON_UNUSED PyObject *__pyx_self, Py_ssize_t __pyx_v_number, PyObject *__pyx_v_buf); /* proto */
+static PyObject *__pyx_pf_17clickhouse_driver_6varint_write_varint(CYTHON_UNUSED PyObject *__pyx_self, unsigned PY_LONG_LONG __pyx_v_number, PyObject *__pyx_v_buf); /* proto */
 static PyObject *__pyx_pf_17clickhouse_driver_6varint_2read_varint(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_f); /* proto */
 static PyObject *__pyx_tuple_;
 static PyObject *__pyx_tuple__3;
 static PyObject *__pyx_codeobj__2;
 static PyObject *__pyx_codeobj__4;
 /* Late includes */
 
 /* "clickhouse_driver/varint.pyx":4
  * 
  * 
- * def write_varint(Py_ssize_t number, buf):             # <<<<<<<<<<<<<<
+ * def write_varint(unsigned long long number, buf):             # <<<<<<<<<<<<<<
  *     """
  *     Writes integer of variable length using LEB128.
  */
 
 /* Python wrapper */
 static PyObject *__pyx_pw_17clickhouse_driver_6varint_1write_varint(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
 static char __pyx_doc_17clickhouse_driver_6varint_write_varint[] = "\n    Writes integer of variable length using LEB128.\n    ";
 static PyMethodDef __pyx_mdef_17clickhouse_driver_6varint_1write_varint = {"write_varint", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_17clickhouse_driver_6varint_1write_varint, METH_VARARGS|METH_KEYWORDS, __pyx_doc_17clickhouse_driver_6varint_write_varint};
 static PyObject *__pyx_pw_17clickhouse_driver_6varint_1write_varint(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  Py_ssize_t __pyx_v_number;
+  unsigned PY_LONG_LONG __pyx_v_number;
   PyObject *__pyx_v_buf = 0;
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("write_varint (wrapper)", 0);
   {
@@ -1280,11 +1283,11 @@ static PyObject *__pyx_pw_17clickhouse_driver_6varint_1write_varint(PyObject *__
       goto __pyx_L5_argtuple_error;
     } else {
       values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
       values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
     }
-    __pyx_v_number = __Pyx_PyIndex_AsSsize_t(values[0]); if (unlikely((__pyx_v_number == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 4, __pyx_L3_error)
+    __pyx_v_number = __Pyx_PyInt_As_unsigned_PY_LONG_LONG(values[0]); if (unlikely((__pyx_v_number == (unsigned PY_LONG_LONG)-1) && PyErr_Occurred())) __PYX_ERR(0, 4, __pyx_L3_error)
     __pyx_v_buf = values[1];
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
   __Pyx_RaiseArgtupleInvalid("write_varint", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 4, __pyx_L3_error)
@@ -1298,13 +1301,13 @@ static PyObject *__pyx_pw_17clickhouse_driver_6varint_1write_varint(PyObject *__
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_17clickhouse_driver_6varint_write_varint(CYTHON_UNUSED PyObject *__pyx_self, Py_ssize_t __pyx_v_number, PyObject *__pyx_v_buf) {
-  Py_ssize_t __pyx_v_i;
-  unsigned char __pyx_v_towrite;
+static PyObject *__pyx_pf_17clickhouse_driver_6varint_write_varint(CYTHON_UNUSED PyObject *__pyx_self, unsigned PY_LONG_LONG __pyx_v_number, PyObject *__pyx_v_buf) {
+  unsigned char __pyx_v_to_write;
+  unsigned char __pyx_v_i;
   unsigned char __pyx_v_num_buf[32];
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
   PyObject *__pyx_t_2 = NULL;
@@ -1314,102 +1317,102 @@ static PyObject *__pyx_pf_17clickhouse_driver_6varint_write_varint(CYTHON_UNUSED
   __Pyx_RefNannySetupContext("write_varint", 0);
 
   /* "clickhouse_driver/varint.pyx":8
  *     Writes integer of variable length using LEB128.
  *     """
- *     cdef Py_ssize_t i = 0             # <<<<<<<<<<<<<<
- *     cdef unsigned char towrite
- *     # Py_ssize_t checks integer on function call and
+ *     cdef unsigned char to_write, i = 0             # <<<<<<<<<<<<<<
+ *     # unsigned PY_LONG_LONG checks integer on function call and
+ *     # raises OverflowError if integer overflows unsigned PY_LONG_LONG.
  */
   __pyx_v_i = 0;
 
-  /* "clickhouse_driver/varint.pyx":15
+  /* "clickhouse_driver/varint.pyx":14
  *     cdef unsigned char num_buf[32]
  * 
  *     while True:             # <<<<<<<<<<<<<<
- *         towrite = number & 0x7f
+ *         to_write = number & 0x7f
  *         number >>= 7
  */
   while (1) {
 
-    /* "clickhouse_driver/varint.pyx":16
+    /* "clickhouse_driver/varint.pyx":15
  * 
  *     while True:
- *         towrite = number & 0x7f             # <<<<<<<<<<<<<<
+ *         to_write = number & 0x7f             # <<<<<<<<<<<<<<
  *         number >>= 7
  *         if number:
  */
-    __pyx_v_towrite = (__pyx_v_number & 0x7f);
+    __pyx_v_to_write = (__pyx_v_number & 0x7f);
 
-    /* "clickhouse_driver/varint.pyx":17
+    /* "clickhouse_driver/varint.pyx":16
  *     while True:
- *         towrite = number & 0x7f
+ *         to_write = number & 0x7f
  *         number >>= 7             # <<<<<<<<<<<<<<
  *         if number:
- *             num_buf[i] = towrite | 0x80
+ *             num_buf[i] = to_write | 0x80
  */
     __pyx_v_number = (__pyx_v_number >> 7);
 
-    /* "clickhouse_driver/varint.pyx":18
- *         towrite = number & 0x7f
+    /* "clickhouse_driver/varint.pyx":17
+ *         to_write = number & 0x7f
  *         number >>= 7
  *         if number:             # <<<<<<<<<<<<<<
- *             num_buf[i] = towrite | 0x80
+ *             num_buf[i] = to_write | 0x80
  *             i += 1
  */
     __pyx_t_1 = (__pyx_v_number != 0);
     if (__pyx_t_1) {
 
-      /* "clickhouse_driver/varint.pyx":19
+      /* "clickhouse_driver/varint.pyx":18
  *         number >>= 7
  *         if number:
- *             num_buf[i] = towrite | 0x80             # <<<<<<<<<<<<<<
+ *             num_buf[i] = to_write | 0x80             # <<<<<<<<<<<<<<
  *             i += 1
  *         else:
  */
-      (__pyx_v_num_buf[__pyx_v_i]) = (__pyx_v_towrite | 0x80);
+      (__pyx_v_num_buf[__pyx_v_i]) = (__pyx_v_to_write | 0x80);
 
-      /* "clickhouse_driver/varint.pyx":20
+      /* "clickhouse_driver/varint.pyx":19
  *         if number:
- *             num_buf[i] = towrite | 0x80
+ *             num_buf[i] = to_write | 0x80
  *             i += 1             # <<<<<<<<<<<<<<
  *         else:
- *             num_buf[i] = towrite
+ *             num_buf[i] = to_write
  */
       __pyx_v_i = (__pyx_v_i + 1);
 
-      /* "clickhouse_driver/varint.pyx":18
- *         towrite = number & 0x7f
+      /* "clickhouse_driver/varint.pyx":17
+ *         to_write = number & 0x7f
  *         number >>= 7
  *         if number:             # <<<<<<<<<<<<<<
- *             num_buf[i] = towrite | 0x80
+ *             num_buf[i] = to_write | 0x80
  *             i += 1
  */
       goto __pyx_L5;
     }
 
-    /* "clickhouse_driver/varint.pyx":22
+    /* "clickhouse_driver/varint.pyx":21
  *             i += 1
  *         else:
- *             num_buf[i] = towrite             # <<<<<<<<<<<<<<
+ *             num_buf[i] = to_write             # <<<<<<<<<<<<<<
  *             i += 1
  *             break
  */
     /*else*/ {
-      (__pyx_v_num_buf[__pyx_v_i]) = __pyx_v_towrite;
+      (__pyx_v_num_buf[__pyx_v_i]) = __pyx_v_to_write;
 
-      /* "clickhouse_driver/varint.pyx":23
+      /* "clickhouse_driver/varint.pyx":22
  *         else:
- *             num_buf[i] = towrite
+ *             num_buf[i] = to_write
  *             i += 1             # <<<<<<<<<<<<<<
  *             break
  * 
  */
       __pyx_v_i = (__pyx_v_i + 1);
 
-      /* "clickhouse_driver/varint.pyx":24
- *             num_buf[i] = towrite
+      /* "clickhouse_driver/varint.pyx":23
+ *             num_buf[i] = to_write
  *             i += 1
  *             break             # <<<<<<<<<<<<<<
  * 
  *     buf.write(PyBytes_FromStringAndSize(<char *>num_buf, i))
  */
@@ -1417,20 +1420,20 @@ static PyObject *__pyx_pf_17clickhouse_driver_6varint_write_varint(CYTHON_UNUSED
     }
     __pyx_L5:;
   }
   __pyx_L4_break:;
 
-  /* "clickhouse_driver/varint.pyx":26
+  /* "clickhouse_driver/varint.pyx":25
  *             break
  * 
  *     buf.write(PyBytes_FromStringAndSize(<char *>num_buf, i))             # <<<<<<<<<<<<<<
  * 
  * 
  */
-  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_buf, __pyx_n_s_write); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 26, __pyx_L1_error)
+  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_buf, __pyx_n_s_write); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 25, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = PyBytes_FromStringAndSize(((char *)__pyx_v_num_buf), __pyx_v_i); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 26, __pyx_L1_error)
+  __pyx_t_4 = PyBytes_FromStringAndSize(((char *)__pyx_v_num_buf), __pyx_v_i); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 25, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_4);
   __pyx_t_5 = NULL;
   if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_3))) {
     __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_3);
     if (likely(__pyx_t_5)) {
@@ -1441,19 +1444,19 @@ static PyObject *__pyx_pf_17clickhouse_driver_6varint_write_varint(CYTHON_UNUSED
     }
   }
   __pyx_t_2 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_5, __pyx_t_4) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4);
   __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 26, __pyx_L1_error)
+  if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 25, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
   /* "clickhouse_driver/varint.pyx":4
  * 
  * 
- * def write_varint(Py_ssize_t number, buf):             # <<<<<<<<<<<<<<
+ * def write_varint(unsigned long long number, buf):             # <<<<<<<<<<<<<<
  *     """
  *     Writes integer of variable length using LEB128.
  */
 
   /* function exit code */
@@ -1470,11 +1473,11 @@ static PyObject *__pyx_pf_17clickhouse_driver_6varint_write_varint(CYTHON_UNUSED
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "clickhouse_driver/varint.pyx":29
+/* "clickhouse_driver/varint.pyx":28
  * 
  * 
  * def read_varint(f):             # <<<<<<<<<<<<<<
  *     """
  *     Reads integer of variable length using LEB128.
@@ -1494,63 +1497,63 @@ static PyObject *__pyx_pw_17clickhouse_driver_6varint_3read_varint(PyObject *__p
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
 static PyObject *__pyx_pf_17clickhouse_driver_6varint_2read_varint(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_f) {
-  Py_ssize_t __pyx_v_shift;
-  Py_ssize_t __pyx_v_result;
-  unsigned char __pyx_v_i;
+  unsigned char __pyx_v_shift;
+  unsigned PY_LONG_LONG __pyx_v_i;
+  unsigned PY_LONG_LONG __pyx_v_result;
   PyObject *__pyx_v_read_one = NULL;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
-  unsigned char __pyx_t_4;
+  unsigned PY_LONG_LONG __pyx_t_4;
   int __pyx_t_5;
   __Pyx_RefNannySetupContext("read_varint", 0);
 
-  /* "clickhouse_driver/varint.pyx":33
+  /* "clickhouse_driver/varint.pyx":32
  *     Reads integer of variable length using LEB128.
  *     """
- *     cdef Py_ssize_t shift = 0             # <<<<<<<<<<<<<<
- *     cdef Py_ssize_t result = 0
- *     cdef unsigned char i
+ *     cdef unsigned char shift = 0             # <<<<<<<<<<<<<<
+ *     cdef unsigned long long i, result = 0
+ * 
  */
   __pyx_v_shift = 0;
 
-  /* "clickhouse_driver/varint.pyx":34
+  /* "clickhouse_driver/varint.pyx":33
  *     """
- *     cdef Py_ssize_t shift = 0
- *     cdef Py_ssize_t result = 0             # <<<<<<<<<<<<<<
- *     cdef unsigned char i
+ *     cdef unsigned char shift = 0
+ *     cdef unsigned long long i, result = 0             # <<<<<<<<<<<<<<
  * 
+ *     read_one = f.read_one
  */
   __pyx_v_result = 0;
 
-  /* "clickhouse_driver/varint.pyx":37
- *     cdef unsigned char i
+  /* "clickhouse_driver/varint.pyx":35
+ *     cdef unsigned long long i, result = 0
  * 
  *     read_one = f.read_one             # <<<<<<<<<<<<<<
  * 
  *     while True:
  */
-  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_f, __pyx_n_s_read_one); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 37, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_f, __pyx_n_s_read_one); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 35, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_v_read_one = __pyx_t_1;
   __pyx_t_1 = 0;
 
-  /* "clickhouse_driver/varint.pyx":39
+  /* "clickhouse_driver/varint.pyx":37
  *     read_one = f.read_one
  * 
  *     while True:             # <<<<<<<<<<<<<<
  *         i = read_one()
  *         result |= (i & 0x7f) << shift
  */
   while (1) {
 
-    /* "clickhouse_driver/varint.pyx":40
+    /* "clickhouse_driver/varint.pyx":38
  * 
  *     while True:
  *         i = read_one()             # <<<<<<<<<<<<<<
  *         result |= (i & 0x7f) << shift
  *         shift += 7
@@ -1566,78 +1569,78 @@ static PyObject *__pyx_pf_17clickhouse_driver_6varint_2read_varint(CYTHON_UNUSED
         __Pyx_DECREF_SET(__pyx_t_2, function);
       }
     }
     __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3) : __Pyx_PyObject_CallNoArg(__pyx_t_2);
     __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
-    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 40, __pyx_L1_error)
+    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 38, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __pyx_t_4 = __Pyx_PyInt_As_unsigned_char(__pyx_t_1); if (unlikely((__pyx_t_4 == (unsigned char)-1) && PyErr_Occurred())) __PYX_ERR(0, 40, __pyx_L1_error)
+    __pyx_t_4 = __Pyx_PyInt_As_unsigned_PY_LONG_LONG(__pyx_t_1); if (unlikely((__pyx_t_4 == (unsigned PY_LONG_LONG)-1) && PyErr_Occurred())) __PYX_ERR(0, 38, __pyx_L1_error)
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
     __pyx_v_i = __pyx_t_4;
 
-    /* "clickhouse_driver/varint.pyx":41
+    /* "clickhouse_driver/varint.pyx":39
  *     while True:
  *         i = read_one()
  *         result |= (i & 0x7f) << shift             # <<<<<<<<<<<<<<
  *         shift += 7
  *         if i < 0x80:
  */
     __pyx_v_result = (__pyx_v_result | ((__pyx_v_i & 0x7f) << __pyx_v_shift));
 
-    /* "clickhouse_driver/varint.pyx":42
+    /* "clickhouse_driver/varint.pyx":40
  *         i = read_one()
  *         result |= (i & 0x7f) << shift
  *         shift += 7             # <<<<<<<<<<<<<<
  *         if i < 0x80:
  *             break
  */
     __pyx_v_shift = (__pyx_v_shift + 7);
 
-    /* "clickhouse_driver/varint.pyx":43
+    /* "clickhouse_driver/varint.pyx":41
  *         result |= (i & 0x7f) << shift
  *         shift += 7
  *         if i < 0x80:             # <<<<<<<<<<<<<<
  *             break
  * 
  */
     __pyx_t_5 = ((__pyx_v_i < 0x80) != 0);
     if (__pyx_t_5) {
 
-      /* "clickhouse_driver/varint.pyx":44
+      /* "clickhouse_driver/varint.pyx":42
  *         shift += 7
  *         if i < 0x80:
  *             break             # <<<<<<<<<<<<<<
  * 
  *     return result
  */
       goto __pyx_L4_break;
 
-      /* "clickhouse_driver/varint.pyx":43
+      /* "clickhouse_driver/varint.pyx":41
  *         result |= (i & 0x7f) << shift
  *         shift += 7
  *         if i < 0x80:             # <<<<<<<<<<<<<<
  *             break
  * 
  */
     }
   }
   __pyx_L4_break:;
 
-  /* "clickhouse_driver/varint.pyx":46
+  /* "clickhouse_driver/varint.pyx":44
  *             break
  * 
  *     return result             # <<<<<<<<<<<<<<
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyInt_FromSsize_t(__pyx_v_result); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 46, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_unsigned_PY_LONG_LONG(__pyx_v_result); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 44, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "clickhouse_driver/varint.pyx":29
+  /* "clickhouse_driver/varint.pyx":28
  * 
  * 
  * def read_varint(f):             # <<<<<<<<<<<<<<
  *     """
  *     Reads integer of variable length using LEB128.
@@ -1716,11 +1719,11 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_n_s_read_one, __pyx_k_read_one, sizeof(__pyx_k_read_one), 0, 0, 1, 1},
   {&__pyx_n_s_read_varint, __pyx_k_read_varint, sizeof(__pyx_k_read_varint), 0, 0, 1, 1},
   {&__pyx_n_s_result, __pyx_k_result, sizeof(__pyx_k_result), 0, 0, 1, 1},
   {&__pyx_n_s_shift, __pyx_k_shift, sizeof(__pyx_k_shift), 0, 0, 1, 1},
   {&__pyx_n_s_test, __pyx_k_test, sizeof(__pyx_k_test), 0, 0, 1, 1},
-  {&__pyx_n_s_towrite, __pyx_k_towrite, sizeof(__pyx_k_towrite), 0, 0, 1, 1},
+  {&__pyx_n_s_to_write, __pyx_k_to_write, sizeof(__pyx_k_to_write), 0, 0, 1, 1},
   {&__pyx_n_s_write, __pyx_k_write, sizeof(__pyx_k_write), 0, 0, 1, 1},
   {&__pyx_n_s_write_varint, __pyx_k_write_varint, sizeof(__pyx_k_write_varint), 0, 0, 1, 1},
   {0, 0, 0, 0, 0, 0, 0}
 };
 static CYTHON_SMALL_CODE int __Pyx_InitCachedBuiltins(void) {
@@ -1732,30 +1735,30 @@ static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) {
   __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0);
 
   /* "clickhouse_driver/varint.pyx":4
  * 
  * 
- * def write_varint(Py_ssize_t number, buf):             # <<<<<<<<<<<<<<
+ * def write_varint(unsigned long long number, buf):             # <<<<<<<<<<<<<<
  *     """
  *     Writes integer of variable length using LEB128.
  */
-  __pyx_tuple_ = PyTuple_Pack(5, __pyx_n_s_number, __pyx_n_s_buf, __pyx_n_s_i, __pyx_n_s_towrite, __pyx_n_s_num_buf); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 4, __pyx_L1_error)
+  __pyx_tuple_ = PyTuple_Pack(5, __pyx_n_s_number, __pyx_n_s_buf, __pyx_n_s_to_write, __pyx_n_s_i, __pyx_n_s_num_buf); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 4, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_tuple_);
   __Pyx_GIVEREF(__pyx_tuple_);
   __pyx_codeobj__2 = (PyObject*)__Pyx_PyCode_New(2, 0, 5, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple_, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_clickhouse_driver_varint_pyx, __pyx_n_s_write_varint, 4, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__2)) __PYX_ERR(0, 4, __pyx_L1_error)
 
-  /* "clickhouse_driver/varint.pyx":29
+  /* "clickhouse_driver/varint.pyx":28
  * 
  * 
  * def read_varint(f):             # <<<<<<<<<<<<<<
  *     """
  *     Reads integer of variable length using LEB128.
  */
-  __pyx_tuple__3 = PyTuple_Pack(5, __pyx_n_s_f, __pyx_n_s_shift, __pyx_n_s_result, __pyx_n_s_i, __pyx_n_s_read_one); if (unlikely(!__pyx_tuple__3)) __PYX_ERR(0, 29, __pyx_L1_error)
+  __pyx_tuple__3 = PyTuple_Pack(5, __pyx_n_s_f, __pyx_n_s_shift, __pyx_n_s_i, __pyx_n_s_result, __pyx_n_s_read_one); if (unlikely(!__pyx_tuple__3)) __PYX_ERR(0, 28, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_tuple__3);
   __Pyx_GIVEREF(__pyx_tuple__3);
-  __pyx_codeobj__4 = (PyObject*)__Pyx_PyCode_New(1, 0, 5, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__3, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_clickhouse_driver_varint_pyx, __pyx_n_s_read_varint, 29, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__4)) __PYX_ERR(0, 29, __pyx_L1_error)
+  __pyx_codeobj__4 = (PyObject*)__Pyx_PyCode_New(1, 0, 5, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__3, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_clickhouse_driver_varint_pyx, __pyx_n_s_read_varint, 28, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__4)) __PYX_ERR(0, 28, __pyx_L1_error)
   __Pyx_RefNannyFinishContext();
   return 0;
   __pyx_L1_error:;
   __Pyx_RefNannyFinishContext();
   return -1;
@@ -2056,29 +2059,29 @@ if (!__Pyx_RefNanny) {
   #endif
 
   /* "clickhouse_driver/varint.pyx":4
  * 
  * 
- * def write_varint(Py_ssize_t number, buf):             # <<<<<<<<<<<<<<
+ * def write_varint(unsigned long long number, buf):             # <<<<<<<<<<<<<<
  *     """
  *     Writes integer of variable length using LEB128.
  */
   __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_17clickhouse_driver_6varint_1write_varint, NULL, __pyx_n_s_clickhouse_driver_varint); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   if (PyDict_SetItem(__pyx_d, __pyx_n_s_write_varint, __pyx_t_1) < 0) __PYX_ERR(0, 4, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "clickhouse_driver/varint.pyx":29
+  /* "clickhouse_driver/varint.pyx":28
  * 
  * 
  * def read_varint(f):             # <<<<<<<<<<<<<<
  *     """
  *     Reads integer of variable length using LEB128.
  */
-  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_17clickhouse_driver_6varint_3read_varint, NULL, __pyx_n_s_clickhouse_driver_varint); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 29, __pyx_L1_error)
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_17clickhouse_driver_6varint_3read_varint, NULL, __pyx_n_s_clickhouse_driver_varint); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 28, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_read_varint, __pyx_t_1) < 0) __PYX_ERR(0, 29, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_read_varint, __pyx_t_1) < 0) __PYX_ERR(0, 28, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
   /* "clickhouse_driver/varint.pyx":1
  * from cpython cimport Py_INCREF, PyBytes_FromStringAndSize             # <<<<<<<<<<<<<<
  * 
@@ -2898,58 +2901,89 @@ bad:
             }\
         }\
         return (target_type) value;\
     }
 
+/* CIntToPy */
+static CYTHON_INLINE PyObject* __Pyx_PyInt_From_unsigned_PY_LONG_LONG(unsigned PY_LONG_LONG value) {
+    const unsigned PY_LONG_LONG neg_one = (unsigned PY_LONG_LONG) ((unsigned PY_LONG_LONG) 0 - (unsigned PY_LONG_LONG) 1), const_zero = (unsigned PY_LONG_LONG) 0;
+    const int is_unsigned = neg_one > const_zero;
+    if (is_unsigned) {
+        if (sizeof(unsigned PY_LONG_LONG) < sizeof(long)) {
+            return PyInt_FromLong((long) value);
+        } else if (sizeof(unsigned PY_LONG_LONG) <= sizeof(unsigned long)) {
+            return PyLong_FromUnsignedLong((unsigned long) value);
+#ifdef HAVE_LONG_LONG
+        } else if (sizeof(unsigned PY_LONG_LONG) <= sizeof(unsigned PY_LONG_LONG)) {
+            return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value);
+#endif
+        }
+    } else {
+        if (sizeof(unsigned PY_LONG_LONG) <= sizeof(long)) {
+            return PyInt_FromLong((long) value);
+#ifdef HAVE_LONG_LONG
+        } else if (sizeof(unsigned PY_LONG_LONG) <= sizeof(PY_LONG_LONG)) {
+            return PyLong_FromLongLong((PY_LONG_LONG) value);
+#endif
+        }
+    }
+    {
+        int one = 1; int little = (int)*(unsigned char *)&one;
+        unsigned char *bytes = (unsigned char *)&value;
+        return _PyLong_FromByteArray(bytes, sizeof(unsigned PY_LONG_LONG),
+                                     little, !is_unsigned);
+    }
+}
+
 /* CIntFromPy */
-static CYTHON_INLINE unsigned char __Pyx_PyInt_As_unsigned_char(PyObject *x) {
-    const unsigned char neg_one = (unsigned char) ((unsigned char) 0 - (unsigned char) 1), const_zero = (unsigned char) 0;
+static CYTHON_INLINE unsigned PY_LONG_LONG __Pyx_PyInt_As_unsigned_PY_LONG_LONG(PyObject *x) {
+    const unsigned PY_LONG_LONG neg_one = (unsigned PY_LONG_LONG) ((unsigned PY_LONG_LONG) 0 - (unsigned PY_LONG_LONG) 1), const_zero = (unsigned PY_LONG_LONG) 0;
     const int is_unsigned = neg_one > const_zero;
 #if PY_MAJOR_VERSION < 3
     if (likely(PyInt_Check(x))) {
-        if (sizeof(unsigned char) < sizeof(long)) {
-            __PYX_VERIFY_RETURN_INT(unsigned char, long, PyInt_AS_LONG(x))
+        if (sizeof(unsigned PY_LONG_LONG) < sizeof(long)) {
+            __PYX_VERIFY_RETURN_INT(unsigned PY_LONG_LONG, long, PyInt_AS_LONG(x))
         } else {
             long val = PyInt_AS_LONG(x);
             if (is_unsigned && unlikely(val < 0)) {
                 goto raise_neg_overflow;
             }
-            return (unsigned char) val;
+            return (unsigned PY_LONG_LONG) val;
         }
     } else
 #endif
     if (likely(PyLong_Check(x))) {
         if (is_unsigned) {
 #if CYTHON_USE_PYLONG_INTERNALS
             const digit* digits = ((PyLongObject*)x)->ob_digit;
             switch (Py_SIZE(x)) {
-                case  0: return (unsigned char) 0;
-                case  1: __PYX_VERIFY_RETURN_INT(unsigned char, digit, digits[0])
+                case  0: return (unsigned PY_LONG_LONG) 0;
+                case  1: __PYX_VERIFY_RETURN_INT(unsigned PY_LONG_LONG, digit, digits[0])
                 case 2:
-                    if (8 * sizeof(unsigned char) > 1 * PyLong_SHIFT) {
+                    if (8 * sizeof(unsigned PY_LONG_LONG) > 1 * PyLong_SHIFT) {
                         if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) {
-                            __PYX_VERIFY_RETURN_INT(unsigned char, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
-                        } else if (8 * sizeof(unsigned char) >= 2 * PyLong_SHIFT) {
-                            return (unsigned char) (((((unsigned char)digits[1]) << PyLong_SHIFT) | (unsigned char)digits[0]));
+                            __PYX_VERIFY_RETURN_INT(unsigned PY_LONG_LONG, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
+                        } else if (8 * sizeof(unsigned PY_LONG_LONG) >= 2 * PyLong_SHIFT) {
+                            return (unsigned PY_LONG_LONG) (((((unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0]));
                         }
                     }
                     break;
                 case 3:
-                    if (8 * sizeof(unsigned char) > 2 * PyLong_SHIFT) {
+                    if (8 * sizeof(unsigned PY_LONG_LONG) > 2 * PyLong_SHIFT) {
                         if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) {
-                            __PYX_VERIFY_RETURN_INT(unsigned char, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
-                        } else if (8 * sizeof(unsigned char) >= 3 * PyLong_SHIFT) {
-                            return (unsigned char) (((((((unsigned char)digits[2]) << PyLong_SHIFT) | (unsigned char)digits[1]) << PyLong_SHIFT) | (unsigned char)digits[0]));
+                            __PYX_VERIFY_RETURN_INT(unsigned PY_LONG_LONG, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
+                        } else if (8 * sizeof(unsigned PY_LONG_LONG) >= 3 * PyLong_SHIFT) {
+                            return (unsigned PY_LONG_LONG) (((((((unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0]));
                         }
                     }
                     break;
                 case 4:
-                    if (8 * sizeof(unsigned char) > 3 * PyLong_SHIFT) {
+                    if (8 * sizeof(unsigned PY_LONG_LONG) > 3 * PyLong_SHIFT) {
                         if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) {
-                            __PYX_VERIFY_RETURN_INT(unsigned char, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
-                        } else if (8 * sizeof(unsigned char) >= 4 * PyLong_SHIFT) {
-                            return (unsigned char) (((((((((unsigned char)digits[3]) << PyLong_SHIFT) | (unsigned char)digits[2]) << PyLong_SHIFT) | (unsigned char)digits[1]) << PyLong_SHIFT) | (unsigned char)digits[0]));
+                            __PYX_VERIFY_RETURN_INT(unsigned PY_LONG_LONG, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
+                        } else if (8 * sizeof(unsigned PY_LONG_LONG) >= 4 * PyLong_SHIFT) {
+                            return (unsigned PY_LONG_LONG) (((((((((unsigned PY_LONG_LONG)digits[3]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0]));
                         }
                     }
                     break;
             }
 #endif
@@ -2959,99 +2993,99 @@ static CYTHON_INLINE unsigned char __Pyx_PyInt_As_unsigned_char(PyObject *x) {
             }
 #else
             {
                 int result = PyObject_RichCompareBool(x, Py_False, Py_LT);
                 if (unlikely(result < 0))
-                    return (unsigned char) -1;
+                    return (unsigned PY_LONG_LONG) -1;
                 if (unlikely(result == 1))
                     goto raise_neg_overflow;
             }
 #endif
-            if (sizeof(unsigned char) <= sizeof(unsigned long)) {
-                __PYX_VERIFY_RETURN_INT_EXC(unsigned char, unsigned long, PyLong_AsUnsignedLong(x))
+            if (sizeof(unsigned PY_LONG_LONG) <= sizeof(unsigned long)) {
+                __PYX_VERIFY_RETURN_INT_EXC(unsigned PY_LONG_LONG, unsigned long, PyLong_AsUnsignedLong(x))
 #ifdef HAVE_LONG_LONG
-            } else if (sizeof(unsigned char) <= sizeof(unsigned PY_LONG_LONG)) {
-                __PYX_VERIFY_RETURN_INT_EXC(unsigned char, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x))
+            } else if (sizeof(unsigned PY_LONG_LONG) <= sizeof(unsigned PY_LONG_LONG)) {
+                __PYX_VERIFY_RETURN_INT_EXC(unsigned PY_LONG_LONG, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x))
 #endif
             }
         } else {
 #if CYTHON_USE_PYLONG_INTERNALS
             const digit* digits = ((PyLongObject*)x)->ob_digit;
             switch (Py_SIZE(x)) {
-                case  0: return (unsigned char) 0;
-                case -1: __PYX_VERIFY_RETURN_INT(unsigned char, sdigit, (sdigit) (-(sdigit)digits[0]))
-                case  1: __PYX_VERIFY_RETURN_INT(unsigned char,  digit, +digits[0])
+                case  0: return (unsigned PY_LONG_LONG) 0;
+                case -1: __PYX_VERIFY_RETURN_INT(unsigned PY_LONG_LONG, sdigit, (sdigit) (-(sdigit)digits[0]))
+                case  1: __PYX_VERIFY_RETURN_INT(unsigned PY_LONG_LONG,  digit, +digits[0])
                 case -2:
-                    if (8 * sizeof(unsigned char) - 1 > 1 * PyLong_SHIFT) {
+                    if (8 * sizeof(unsigned PY_LONG_LONG) - 1 > 1 * PyLong_SHIFT) {
                         if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) {
-                            __PYX_VERIFY_RETURN_INT(unsigned char, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
-                        } else if (8 * sizeof(unsigned char) - 1 > 2 * PyLong_SHIFT) {
-                            return (unsigned char) (((unsigned char)-1)*(((((unsigned char)digits[1]) << PyLong_SHIFT) | (unsigned char)digits[0])));
+                            __PYX_VERIFY_RETURN_INT(unsigned PY_LONG_LONG, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
+                        } else if (8 * sizeof(unsigned PY_LONG_LONG) - 1 > 2 * PyLong_SHIFT) {
+                            return (unsigned PY_LONG_LONG) (((unsigned PY_LONG_LONG)-1)*(((((unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])));
                         }
                     }
                     break;
                 case 2:
-                    if (8 * sizeof(unsigned char) > 1 * PyLong_SHIFT) {
+                    if (8 * sizeof(unsigned PY_LONG_LONG) > 1 * PyLong_SHIFT) {
                         if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) {
-                            __PYX_VERIFY_RETURN_INT(unsigned char, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
-                        } else if (8 * sizeof(unsigned char) - 1 > 2 * PyLong_SHIFT) {
-                            return (unsigned char) ((((((unsigned char)digits[1]) << PyLong_SHIFT) | (unsigned char)digits[0])));
+                            __PYX_VERIFY_RETURN_INT(unsigned PY_LONG_LONG, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
+                        } else if (8 * sizeof(unsigned PY_LONG_LONG) - 1 > 2 * PyLong_SHIFT) {
+                            return (unsigned PY_LONG_LONG) ((((((unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])));
                         }
                     }
                     break;
                 case -3:
-                    if (8 * sizeof(unsigned char) - 1 > 2 * PyLong_SHIFT) {
+                    if (8 * sizeof(unsigned PY_LONG_LONG) - 1 > 2 * PyLong_SHIFT) {
                         if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) {
-                            __PYX_VERIFY_RETURN_INT(unsigned char, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
-                        } else if (8 * sizeof(unsigned char) - 1 > 3 * PyLong_SHIFT) {
-                            return (unsigned char) (((unsigned char)-1)*(((((((unsigned char)digits[2]) << PyLong_SHIFT) | (unsigned char)digits[1]) << PyLong_SHIFT) | (unsigned char)digits[0])));
+                            __PYX_VERIFY_RETURN_INT(unsigned PY_LONG_LONG, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
+                        } else if (8 * sizeof(unsigned PY_LONG_LONG) - 1 > 3 * PyLong_SHIFT) {
+                            return (unsigned PY_LONG_LONG) (((unsigned PY_LONG_LONG)-1)*(((((((unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])));
                         }
                     }
                     break;
                 case 3:
-                    if (8 * sizeof(unsigned char) > 2 * PyLong_SHIFT) {
+                    if (8 * sizeof(unsigned PY_LONG_LONG) > 2 * PyLong_SHIFT) {
                         if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) {
-                            __PYX_VERIFY_RETURN_INT(unsigned char, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
-                        } else if (8 * sizeof(unsigned char) - 1 > 3 * PyLong_SHIFT) {
-                            return (unsigned char) ((((((((unsigned char)digits[2]) << PyLong_SHIFT) | (unsigned char)digits[1]) << PyLong_SHIFT) | (unsigned char)digits[0])));
+                            __PYX_VERIFY_RETURN_INT(unsigned PY_LONG_LONG, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
+                        } else if (8 * sizeof(unsigned PY_LONG_LONG) - 1 > 3 * PyLong_SHIFT) {
+                            return (unsigned PY_LONG_LONG) ((((((((unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])));
                         }
                     }
                     break;
                 case -4:
-                    if (8 * sizeof(unsigned char) - 1 > 3 * PyLong_SHIFT) {
+                    if (8 * sizeof(unsigned PY_LONG_LONG) - 1 > 3 * PyLong_SHIFT) {
                         if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) {
-                            __PYX_VERIFY_RETURN_INT(unsigned char, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
-                        } else if (8 * sizeof(unsigned char) - 1 > 4 * PyLong_SHIFT) {
-                            return (unsigned char) (((unsigned char)-1)*(((((((((unsigned char)digits[3]) << PyLong_SHIFT) | (unsigned char)digits[2]) << PyLong_SHIFT) | (unsigned char)digits[1]) << PyLong_SHIFT) | (unsigned char)digits[0])));
+                            __PYX_VERIFY_RETURN_INT(unsigned PY_LONG_LONG, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
+                        } else if (8 * sizeof(unsigned PY_LONG_LONG) - 1 > 4 * PyLong_SHIFT) {
+                            return (unsigned PY_LONG_LONG) (((unsigned PY_LONG_LONG)-1)*(((((((((unsigned PY_LONG_LONG)digits[3]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])));
                         }
                     }
                     break;
                 case 4:
-                    if (8 * sizeof(unsigned char) > 3 * PyLong_SHIFT) {
+                    if (8 * sizeof(unsigned PY_LONG_LONG) > 3 * PyLong_SHIFT) {
                         if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) {
-                            __PYX_VERIFY_RETURN_INT(unsigned char, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
-                        } else if (8 * sizeof(unsigned char) - 1 > 4 * PyLong_SHIFT) {
-                            return (unsigned char) ((((((((((unsigned char)digits[3]) << PyLong_SHIFT) | (unsigned char)digits[2]) << PyLong_SHIFT) | (unsigned char)digits[1]) << PyLong_SHIFT) | (unsigned char)digits[0])));
+                            __PYX_VERIFY_RETURN_INT(unsigned PY_LONG_LONG, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
+                        } else if (8 * sizeof(unsigned PY_LONG_LONG) - 1 > 4 * PyLong_SHIFT) {
+                            return (unsigned PY_LONG_LONG) ((((((((((unsigned PY_LONG_LONG)digits[3]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])));
                         }
                     }
                     break;
             }
 #endif
-            if (sizeof(unsigned char) <= sizeof(long)) {
-                __PYX_VERIFY_RETURN_INT_EXC(unsigned char, long, PyLong_AsLong(x))
+            if (sizeof(unsigned PY_LONG_LONG) <= sizeof(long)) {
+                __PYX_VERIFY_RETURN_INT_EXC(unsigned PY_LONG_LONG, long, PyLong_AsLong(x))
 #ifdef HAVE_LONG_LONG
-            } else if (sizeof(unsigned char) <= sizeof(PY_LONG_LONG)) {
-                __PYX_VERIFY_RETURN_INT_EXC(unsigned char, PY_LONG_LONG, PyLong_AsLongLong(x))
+            } else if (sizeof(unsigned PY_LONG_LONG) <= sizeof(PY_LONG_LONG)) {
+                __PYX_VERIFY_RETURN_INT_EXC(unsigned PY_LONG_LONG, PY_LONG_LONG, PyLong_AsLongLong(x))
 #endif
             }
         }
         {
 #if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray)
             PyErr_SetString(PyExc_RuntimeError,
                             "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers");
 #else
-            unsigned char val;
+            unsigned PY_LONG_LONG val;
             PyObject *v = __Pyx_PyNumber_IntOrLong(x);
  #if PY_MAJOR_VERSION < 3
             if (likely(v) && !PyLong_Check(v)) {
                 PyObject *tmp = v;
                 v = PyNumber_Long(tmp);
@@ -3067,28 +3101,28 @@ static CYTHON_INLINE unsigned char __Pyx_PyInt_As_unsigned_char(PyObject *x) {
                 Py_DECREF(v);
                 if (likely(!ret))
                     return val;
             }
 #endif
-            return (unsigned char) -1;
+            return (unsigned PY_LONG_LONG) -1;
         }
     } else {
-        unsigned char val;
+        unsigned PY_LONG_LONG val;
         PyObject *tmp = __Pyx_PyNumber_IntOrLong(x);
-        if (!tmp) return (unsigned char) -1;
-        val = __Pyx_PyInt_As_unsigned_char(tmp);
+        if (!tmp) return (unsigned PY_LONG_LONG) -1;
+        val = __Pyx_PyInt_As_unsigned_PY_LONG_LONG(tmp);
         Py_DECREF(tmp);
         return val;
     }
 raise_overflow:
     PyErr_SetString(PyExc_OverflowError,
-        "value too large to convert to unsigned char");
-    return (unsigned char) -1;
+        "value too large to convert to unsigned PY_LONG_LONG");
+    return (unsigned PY_LONG_LONG) -1;
 raise_neg_overflow:
     PyErr_SetString(PyExc_OverflowError,
-        "can't convert negative value to unsigned char");
-    return (unsigned char) -1;
+        "can't convert negative value to unsigned PY_LONG_LONG");
+    return (unsigned PY_LONG_LONG) -1;
 }
 
 /* CIntToPy */
 static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) {
     const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0;
diff --git a/clickhouse_driver/varint.pyx b/clickhouse_driver/varint.pyx
index 92d6060..b93c148 100644
--- a/clickhouse_driver/varint.pyx
+++ b/clickhouse_driver/varint.pyx
@@ -1,40 +1,38 @@
 from cpython cimport Py_INCREF, PyBytes_FromStringAndSize
 
 
-def write_varint(Py_ssize_t number, buf):
+def write_varint(unsigned long long number, buf):
     """
     Writes integer of variable length using LEB128.
     """
-    cdef Py_ssize_t i = 0
-    cdef unsigned char towrite
-    # Py_ssize_t checks integer on function call and
-    # raises OverflowError if integer overflows Py_ssize_t.
-    # Long enough for handling Py_ssize_t.
+    cdef unsigned char to_write, i = 0
+    # unsigned PY_LONG_LONG checks integer on function call and
+    # raises OverflowError if integer overflows unsigned PY_LONG_LONG.
+    # Long enough for handling unsigned PY_LONG_LONG.
     cdef unsigned char num_buf[32]
 
     while True:
-        towrite = number & 0x7f
+        to_write = number & 0x7f
         number >>= 7
         if number:
-            num_buf[i] = towrite | 0x80
+            num_buf[i] = to_write | 0x80
             i += 1
         else:
-            num_buf[i] = towrite
+            num_buf[i] = to_write
             i += 1
             break
 
     buf.write(PyBytes_FromStringAndSize(<char *>num_buf, i))
 
 
 def read_varint(f):
     """
     Reads integer of variable length using LEB128.
     """
-    cdef Py_ssize_t shift = 0
-    cdef Py_ssize_t result = 0
-    cdef unsigned char i
+    cdef unsigned char shift = 0
+    cdef unsigned long long i, result = 0
 
     read_one = f.read_one
 
     while True:
         i = read_one()
diff --git a/tests/test_varint.py b/tests/test_varint.py
new file mode 100644
index 0000000..f6d785b
--- /dev/null
+++ b/tests/test_varint.py
@@ -0,0 +1,19 @@
+from io import BytesIO
+from unittest import TestCase
+
+from clickhouse_driver.varint import read_varint, write_varint
+
+
+class VarIntTestCase(TestCase):
+    def test_check_not_negative(self):
+        n = 0x9FFFFFFF
+
+        buf = BytesIO()
+        write_varint(n, buf)
+        val = buf.getvalue()
+        self.assertEqual(b'\xFF\xFF\xFF\xFF\t', val)
+
+        buf = BytesIO(val)
+        buf.read_one = lambda: ord(buf.read(1))
+        m = read_varint(buf)
+        self.assertEqual(m, n)

Vulnerable code: static CYTHON_INLINE unsigned char __Pyx_PyInt_As_unsigned_char(PyObject *);
static const char __pyx_k_towrite[] = "towrite";
static PyObject *__pyx_n_s_towrite;
static PyObject *__pyx_pf_17clickhouse_driver_6varint_write_varint(CYTHON_UNUSED PyObject *__pyx_self, Py_ssize_t __pyx_v_number, PyObject *__pyx_v_buf); /* proto */
 * def write_varint(Py_ssize_t number, buf):             # <<<<<<<<<<<<<<
  Py_ssize_t __pyx_v_number;
    __pyx_v_number = __Pyx_PyIndex_AsSsize_t(values[0]); if (unlikely((__pyx_v_number == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 4, __pyx_L3_error)
static PyObject *__pyx_pf_17clickhouse_driver_6varint_write_varint(CYTHON_UNUSED PyObject *__pyx_self, Py_ssize_t __pyx_v_number, PyObject *__pyx_v_buf) {
  Py_ssize_t __pyx_v_i;
  unsigned char __pyx_v_towrite;
 *     cdef Py_ssize_t i = 0             # <<<<<<<<<<<<<<
 *     cdef unsigned char towrite
 *     # Py_ssize_t checks integer on function call and
  /* "clickhouse_driver/varint.pyx":15
 *         towrite = number & 0x7f
    /* "clickhouse_driver/varint.pyx":16
 *         towrite = number & 0x7f             # <<<<<<<<<<<<<<
    __pyx_v_towrite = (__pyx_v_number & 0x7f);
    /* "clickhouse_driver/varint.pyx":17
 *         towrite = number & 0x7f
 *             num_buf[i] = towrite | 0x80
    /* "clickhouse_driver/varint.pyx":18
 *         towrite = number & 0x7f
 *             num_buf[i] = towrite | 0x80
      /* "clickhouse_driver/varint.pyx":19
 *             num_buf[i] = towrite | 0x80             # <<<<<<<<<<<<<<
      (__pyx_v_num_buf[__pyx_v_i]) = (__pyx_v_towrite | 0x80);
      /* "clickhouse_driver/varint.pyx":20
 *             num_buf[i] = towrite | 0x80
 *             num_buf[i] = towrite
      /* "clickhouse_driver/varint.pyx":18
 *         towrite = number & 0x7f
 *             num_buf[i] = towrite | 0x80
    /* "clickhouse_driver/varint.pyx":22
 *             num_buf[i] = towrite             # <<<<<<<<<<<<<<
      (__pyx_v_num_buf[__pyx_v_i]) = __pyx_v_towrite;
      /* "clickhouse_driver/varint.pyx":23
 *             num_buf[i] = towrite
      /* "clickhouse_driver/varint.pyx":24
 *             num_buf[i] = towrite
  /* "clickhouse_driver/varint.pyx":26
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_buf, __pyx_n_s_write); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 26, __pyx_L1_error)
  __pyx_t_4 = PyBytes_FromStringAndSize(((char *)__pyx_v_num_buf), __pyx_v_i); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 26, __pyx_L1_error)
  if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 26, __pyx_L1_error)
 * def write_varint(Py_ssize_t number, buf):             # <<<<<<<<<<<<<<
/* "clickhouse_driver/varint.pyx":29
  Py_ssize_t __pyx_v_shift;
  Py_ssize_t __pyx_v_result;
  unsigned char __pyx_v_i;
  unsigned char __pyx_t_4;
  /* "clickhouse_driver/varint.pyx":33
 *     cdef Py_ssize_t shift = 0             # <<<<<<<<<<<<<<
 *     cdef Py_ssize_t result = 0
 *     cdef unsigned char i
  /* "clickhouse_driver/varint.pyx":34
 *     cdef Py_ssize_t shift = 0
 *     cdef Py_ssize_t result = 0             # <<<<<<<<<<<<<<
 *     cdef unsigned char i
  /* "clickhouse_driver/varint.pyx":37
 *     cdef unsigned char i
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_f, __pyx_n_s_read_one); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 37, __pyx_L1_error)
  /* "clickhouse_driver/varint.pyx":39
    /* "clickhouse_driver/varint.pyx":40
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 40, __pyx_L1_error)
    __pyx_t_4 = __Pyx_PyInt_As_unsigned_char(__pyx_t_1); if (unlikely((__pyx_t_4 == (unsigned char)-1) && PyErr_Occurred())) __PYX_ERR(0, 40, __pyx_L1_error)
    /* "clickhouse_driver/varint.pyx":41
    /* "clickhouse_driver/varint.pyx":42
    /* "clickhouse_driver/varint.pyx":43
      /* "clickhouse_driver/varint.pyx":44
      /* "clickhouse_driver/varint.pyx":43
  /* "clickhouse_driver/varint.pyx":46
  __pyx_t_1 = PyInt_FromSsize_t(__pyx_v_result); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 46, __pyx_L1_error)
  /* "clickhouse_driver/varint.pyx":29
  {&__pyx_n_s_towrite, __pyx_k_towrite, sizeof(__pyx_k_towrite), 0, 0, 1, 1},
 * def write_varint(Py_ssize_t number, buf):             # <<<<<<<<<<<<<<
  __pyx_tuple_ = PyTuple_Pack(5, __pyx_n_s_number, __pyx_n_s_buf, __pyx_n_s_i, __pyx_n_s_towrite, __pyx_n_s_num_buf); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 4, __pyx_L1_error)
  /* "clickhouse_driver/varint.pyx":29
  __pyx_tuple__3 = PyTuple_Pack(5, __pyx_n_s_f, __pyx_n_s_shift, __pyx_n_s_result, __pyx_n_s_i, __pyx_n_s_read_one); if (unlikely(!__pyx_tuple__3)) __PYX_ERR(0, 29, __pyx_L1_error)
  __pyx_codeobj__4 = (PyObject*)__Pyx_PyCode_New(1, 0, 5, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__3, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_clickhouse_driver_varint_pyx, __pyx_n_s_read_varint, 29, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__4)) __PYX_ERR(0, 29, __pyx_L1_error)
 * def write_varint(Py_ssize_t number, buf):             # <<<<<<<<<<<<<<
  /* "clickhouse_driver/varint.pyx":29
  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_17clickhouse_driver_6varint_3read_varint, NULL, __pyx_n_s_clickhouse_driver_varint); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 29, __pyx_L1_error)
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_read_varint, __pyx_t_1) < 0) __PYX_ERR(0, 29, __pyx_L1_error)
static CYTHON_INLINE unsigned char __Pyx_PyInt_As_unsigned_char(PyObject *x) {
    const unsigned char neg_one = (unsigned char) ((unsigned char) 0 - (unsigned char) 1), const_zero = (unsigned char) 0;
        if (sizeof(unsigned char) < sizeof(long)) {
            __PYX_VERIFY_RETURN_INT(unsigned char, long, PyInt_AS_LONG(x))
            return (unsigned char) val;
                case  0: return (unsigned char) 0;
                case  1: __PYX_VERIFY_RETURN_INT(unsigned char, digit, digits[0])
                    if (8 * sizeof(unsigned char) > 1 * PyLong_SHIFT) {
                            __PYX_VERIFY_RETURN_INT(unsigned char, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                        } else if (8 * sizeof(unsigned char) >= 2 * PyLong_SHIFT) {
                            return (unsigned char) (((((unsigned char)digits[1]) << PyLong_SHIFT) | (unsigned char)digits[0]));
                    if (8 * sizeof(unsigned char) > 2 * PyLong_SHIFT) {
                            __PYX_VERIFY_RETURN_INT(unsigned char, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                        } else if (8 * sizeof(unsigned char) >= 3 * PyLong_SHIFT) {
                            return (unsigned char) (((((((unsigned char)digits[2]) << PyLong_SHIFT) | (unsigned char)digits[1]) << PyLong_SHIFT) | (unsigned char)digits[0]));
                    if (8 * sizeof(unsigned char) > 3 * PyLong_SHIFT) {
                            __PYX_VERIFY_RETURN_INT(unsigned char, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                        } else if (8 * sizeof(unsigned char) >= 4 * PyLong_SHIFT) {
                            return (unsigned char) (((((((((unsigned char)digits[3]) << PyLong_SHIFT) | (unsigned char)digits[2]) << PyLong_SHIFT) | (unsigned char)digits[1]) << PyLong_SHIFT) | (unsigned char)digits[0]));
                    return (unsigned char) -1;
            if (sizeof(unsigned char) <= sizeof(unsigned long)) {
                __PYX_VERIFY_RETURN_INT_EXC(unsigned char, unsigned long, PyLong_AsUnsignedLong(x))
            } else if (sizeof(unsigned char) <= sizeof(unsigned PY_LONG_LONG)) {
                __PYX_VERIFY_RETURN_INT_EXC(unsigned char, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x))
                case  0: return (unsigned char) 0;
                case -1: __PYX_VERIFY_RETURN_INT(unsigned char, sdigit, (sdigit) (-(sdigit)digits[0]))
                case  1: __PYX_VERIFY_RETURN_INT(unsigned char,  digit, +digits[0])
                    if (8 * sizeof(unsigned char) - 1 > 1 * PyLong_SHIFT) {
                            __PYX_VERIFY_RETURN_INT(unsigned char, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                        } else if (8 * sizeof(unsigned char) - 1 > 2 * PyLong_SHIFT) {
                            return (unsigned char) (((unsigned char)-1)*(((((unsigned char)digits[1]) << PyLong_SHIFT) | (unsigned char)digits[0])));
                    if (8 * sizeof(unsigned char) > 1 * PyLong_SHIFT) {
                            __PYX_VERIFY_RETURN_INT(unsigned char, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                        } else if (8 * sizeof(unsigned char) - 1 > 2 * PyLong_SHIFT) {
                            return (unsigned char) ((((((unsigned char)digits[1]) << PyLong_SHIFT) | (unsigned char)digits[0])));
                    if (8 * sizeof(unsigned char) - 1 > 2 * PyLong_SHIFT) {
                            __PYX_VERIFY_RETURN_INT(unsigned char, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                        } else if (8 * sizeof(unsigned char) - 1 > 3 * PyLong_SHIFT) {
                            return (unsigned char) (((unsigned char)-1)*(((((((unsigned char)digits[2]) << PyLong_SHIFT) | (unsigned char)digits[1]) << PyLong_SHIFT) | (unsigned char)digits[0])));
                    if (8 * sizeof(unsigned char) > 2 * PyLong_SHIFT) {
                            __PYX_VERIFY_RETURN_INT(unsigned char, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                        } else if (8 * sizeof(unsigned char) - 1 > 3 * PyLong_SHIFT) {
                            return (unsigned char) ((((((((unsigned char)digits[2]) << PyLong_SHIFT) | (unsigned char)digits[1]) << PyLong_SHIFT) | (unsigned char)digits[0])));
                    if (8 * sizeof(unsigned char) - 1 > 3 * PyLong_SHIFT) {
                            __PYX_VERIFY_RETURN_INT(unsigned char, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                        } else if (8 * sizeof(unsigned char) - 1 > 4 * PyLong_SHIFT) {
                            return (unsigned char) (((unsigned char)-1)*(((((((((unsigned char)digits[3]) << PyLong_SHIFT) | (unsigned char)digits[2]) << PyLong_SHIFT) | (unsigned char)digits[1]) << PyLong_SHIFT) | (unsigned char)digits[0])));
                    if (8 * sizeof(unsigned char) > 3 * PyLong_SHIFT) {
                            __PYX_VERIFY_RETURN_INT(unsigned char, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                        } else if (8 * sizeof(unsigned char) - 1 > 4 * PyLong_SHIFT) {
                            return (unsigned char) ((((((((((unsigned char)digits[3]) << PyLong_SHIFT) | (unsigned char)digits[2]) << PyLong_SHIFT) | (unsigned char)digits[1]) << PyLong_SHIFT) | (unsigned char)digits[0])));
            if (sizeof(unsigned char) <= sizeof(long)) {
                __PYX_VERIFY_RETURN_INT_EXC(unsigned char, long, PyLong_AsLong(x))
            } else if (sizeof(unsigned char) <= sizeof(PY_LONG_LONG)) {
                __PYX_VERIFY_RETURN_INT_EXC(unsigned char, PY_LONG_LONG, PyLong_AsLongLong(x))
            unsigned char val;
            return (unsigned char) -1;
        unsigned char val;
        if (!tmp) return (unsigned char) -1;
        val = __Pyx_PyInt_As_unsigned_char(tmp);
        "value too large to convert to unsigned char");
    return (unsigned char) -1;
        "can't convert negative value to unsigned char");
    return (unsigned char) -1;
def write_varint(Py_ssize_t number, buf):
    cdef Py_ssize_t i = 0
    cdef unsigned char towrite
    # Py_ssize_t checks integer on function call and
    # raises OverflowError if integer overflows Py_ssize_t.
    # Long enough for handling Py_ssize_t.
        towrite = number & 0x7f
            num_buf[i] = towrite | 0x80
            num_buf[i] = towrite
    cdef Py_ssize_t shift = 0
    cdef Py_ssize_t result = 0
    cdef unsigned char i
Fixed code: /* CIntToPy.proto */
static CYTHON_INLINE PyObject* __Pyx_PyInt_From_unsigned_PY_LONG_LONG(unsigned PY_LONG_LONG value);

static CYTHON_INLINE unsigned PY_LONG_LONG __Pyx_PyInt_As_unsigned_PY_LONG_LONG(PyObject *);
static const char __pyx_k_to_write[] = "to_write";
static PyObject *__pyx_n_s_to_write;
static PyObject *__pyx_pf_17clickhouse_driver_6varint_write_varint(CYTHON_UNUSED PyObject *__pyx_self, unsigned PY_LONG_LONG __pyx_v_number, PyObject *__pyx_v_buf); /* proto */
 * def write_varint(unsigned long long number, buf):             # <<<<<<<<<<<<<<
  unsigned PY_LONG_LONG __pyx_v_number;
    __pyx_v_number = __Pyx_PyInt_As_unsigned_PY_LONG_LONG(values[0]); if (unlikely((__pyx_v_number == (unsigned PY_LONG_LONG)-1) && PyErr_Occurred())) __PYX_ERR(0, 4, __pyx_L3_error)
static PyObject *__pyx_pf_17clickhouse_driver_6varint_write_varint(CYTHON_UNUSED PyObject *__pyx_self, unsigned PY_LONG_LONG __pyx_v_number, PyObject *__pyx_v_buf) {
  unsigned char __pyx_v_to_write;
  unsigned char __pyx_v_i;
 *     cdef unsigned char to_write, i = 0             # <<<<<<<<<<<<<<
 *     # unsigned PY_LONG_LONG checks integer on function call and
 *     # raises OverflowError if integer overflows unsigned PY_LONG_LONG.
  /* "clickhouse_driver/varint.pyx":14
 *         to_write = number & 0x7f
    /* "clickhouse_driver/varint.pyx":15
 *         to_write = number & 0x7f             # <<<<<<<<<<<<<<
    __pyx_v_to_write = (__pyx_v_number & 0x7f);
    /* "clickhouse_driver/varint.pyx":16
 *         to_write = number & 0x7f
 *             num_buf[i] = to_write | 0x80
    /* "clickhouse_driver/varint.pyx":17
 *         to_write = number & 0x7f
 *             num_buf[i] = to_write | 0x80
      /* "clickhouse_driver/varint.pyx":18
 *             num_buf[i] = to_write | 0x80             # <<<<<<<<<<<<<<
      (__pyx_v_num_buf[__pyx_v_i]) = (__pyx_v_to_write | 0x80);
      /* "clickhouse_driver/varint.pyx":19
 *             num_buf[i] = to_write | 0x80
 *             num_buf[i] = to_write
      /* "clickhouse_driver/varint.pyx":17
 *         to_write = number & 0x7f
 *             num_buf[i] = to_write | 0x80
    /* "clickhouse_driver/varint.pyx":21
 *             num_buf[i] = to_write             # <<<<<<<<<<<<<<
      (__pyx_v_num_buf[__pyx_v_i]) = __pyx_v_to_write;
      /* "clickhouse_driver/varint.pyx":22
 *             num_buf[i] = to_write
      /* "clickhouse_driver/varint.pyx":23
 *             num_buf[i] = to_write
  /* "clickhouse_driver/varint.pyx":25
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_buf, __pyx_n_s_write); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 25, __pyx_L1_error)
  __pyx_t_4 = PyBytes_FromStringAndSize(((char *)__pyx_v_num_buf), __pyx_v_i); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 25, __pyx_L1_error)
  if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 25, __pyx_L1_error)
 * def write_varint(unsigned long long number, buf):             # <<<<<<<<<<<<<<
/* "clickhouse_driver/varint.pyx":28
  unsigned char __pyx_v_shift;
  unsigned PY_LONG_LONG __pyx_v_i;
  unsigned PY_LONG_LONG __pyx_v_result;
  unsigned PY_LONG_LONG __pyx_t_4;
  /* "clickhouse_driver/varint.pyx":32
 *     cdef unsigned char shift = 0             # <<<<<<<<<<<<<<
 *     cdef unsigned long long i, result = 0
 * 
  /* "clickhouse_driver/varint.pyx":33
 *     cdef unsigned char shift = 0
 *     cdef unsigned long long i, result = 0             # <<<<<<<<<<<<<<
 *     read_one = f.read_one
  /* "clickhouse_driver/varint.pyx":35
 *     cdef unsigned long long i, result = 0
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_f, __pyx_n_s_read_one); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 35, __pyx_L1_error)
  /* "clickhouse_driver/varint.pyx":37
    /* "clickhouse_driver/varint.pyx":38
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 38, __pyx_L1_error)
    __pyx_t_4 = __Pyx_PyInt_As_unsigned_PY_LONG_LONG(__pyx_t_1); if (unlikely((__pyx_t_4 == (unsigned PY_LONG_LONG)-1) && PyErr_Occurred())) __PYX_ERR(0, 38, __pyx_L1_error)
    /* "clickhouse_driver/varint.pyx":39
    /* "clickhouse_driver/varint.pyx":40
    /* "clickhouse_driver/varint.pyx":41
      /* "clickhouse_driver/varint.pyx":42
      /* "clickhouse_driver/varint.pyx":41
  /* "clickhouse_driver/varint.pyx":44
  __pyx_t_1 = __Pyx_PyInt_From_unsigned_PY_LONG_LONG(__pyx_v_result); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 44, __pyx_L1_error)
  /* "clickhouse_driver/varint.pyx":28
  {&__pyx_n_s_to_write, __pyx_k_to_write, sizeof(__pyx_k_to_write), 0, 0, 1, 1},
 * def write_varint(unsigned long long number, buf):             # <<<<<<<<<<<<<<
  __pyx_tuple_ = PyTuple_Pack(5, __pyx_n_s_number, __pyx_n_s_buf, __pyx_n_s_to_write, __pyx_n_s_i, __pyx_n_s_num_buf); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 4, __pyx_L1_error)
  /* "clickhouse_driver/varint.pyx":28
  __pyx_tuple__3 = PyTuple_Pack(5, __pyx_n_s_f, __pyx_n_s_shift, __pyx_n_s_i, __pyx_n_s_result, __pyx_n_s_read_one); if (unlikely(!__pyx_tuple__3)) __PYX_ERR(0, 28, __pyx_L1_error)
  __pyx_codeobj__4 = (PyObject*)__Pyx_PyCode_New(1, 0, 5, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__3, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_clickhouse_driver_varint_pyx, __pyx_n_s_read_varint, 28, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__4)) __PYX_ERR(0, 28, __pyx_L1_error)
 * def write_varint(unsigned long long number, buf):             # <<<<<<<<<<<<<<
  /* "clickhouse_driver/varint.pyx":28
  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_17clickhouse_driver_6varint_3read_varint, NULL, __pyx_n_s_clickhouse_driver_varint); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 28, __pyx_L1_error)
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_read_varint, __pyx_t_1) < 0) __PYX_ERR(0, 28, __pyx_L1_error)
/* CIntToPy */
static CYTHON_INLINE PyObject* __Pyx_PyInt_From_unsigned_PY_LONG_LONG(unsigned PY_LONG_LONG value) {
    const unsigned PY_LONG_LONG neg_one = (unsigned PY_LONG_LONG) ((unsigned PY_LONG_LONG) 0 - (unsigned PY_LONG_LONG) 1), const_zero = (unsigned PY_LONG_LONG) 0;
    const int is_unsigned = neg_one > const_zero;
    if (is_unsigned) {
        if (sizeof(unsigned PY_LONG_LONG) < sizeof(long)) {
            return PyInt_FromLong((long) value);
        } else if (sizeof(unsigned PY_LONG_LONG) <= sizeof(unsigned long)) {
            return PyLong_FromUnsignedLong((unsigned long) value);
#ifdef HAVE_LONG_LONG
        } else if (sizeof(unsigned PY_LONG_LONG) <= sizeof(unsigned PY_LONG_LONG)) {
            return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value);
#endif
        }
    } else {
        if (sizeof(unsigned PY_LONG_LONG) <= sizeof(long)) {
            return PyInt_FromLong((long) value);
#ifdef HAVE_LONG_LONG
        } else if (sizeof(unsigned PY_LONG_LONG) <= sizeof(PY_LONG_LONG)) {
            return PyLong_FromLongLong((PY_LONG_LONG) value);
#endif
        }
    }
    {
        int one = 1; int little = (int)*(unsigned char *)&one;
        unsigned char *bytes = (unsigned char *)&value;
        return _PyLong_FromByteArray(bytes, sizeof(unsigned PY_LONG_LONG),
                                     little, !is_unsigned);
    }
}

static CYTHON_INLINE unsigned PY_LONG_LONG __Pyx_PyInt_As_unsigned_PY_LONG_LONG(PyObject *x) {
    const unsigned PY_LONG_LONG neg_one = (unsigned PY_LONG_LONG) ((unsigned PY_LONG_LONG) 0 - (unsigned PY_LONG_LONG) 1), const_zero = (unsigned PY_LONG_LONG) 0;
        if (sizeof(unsigned PY_LONG_LONG) < sizeof(long)) {
            __PYX_VERIFY_RETURN_INT(unsigned PY_LONG_LONG, long, PyInt_AS_LONG(x))
            return (unsigned PY_LONG_LONG) val;
                case  0: return (unsigned PY_LONG_LONG) 0;
                case  1: __PYX_VERIFY_RETURN_INT(unsigned PY_LONG_LONG, digit, digits[0])
                    if (8 * sizeof(unsigned PY_LONG_LONG) > 1 * PyLong_SHIFT) {
                            __PYX_VERIFY_RETURN_INT(unsigned PY_LONG_LONG, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                        } else if (8 * sizeof(unsigned PY_LONG_LONG) >= 2 * PyLong_SHIFT) {
                            return (unsigned PY_LONG_LONG) (((((unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0]));
                    if (8 * sizeof(unsigned PY_LONG_LONG) > 2 * PyLong_SHIFT) {
                            __PYX_VERIFY_RETURN_INT(unsigned PY_LONG_LONG, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                        } else if (8 * sizeof(unsigned PY_LONG_LONG) >= 3 * PyLong_SHIFT) {
                            return (unsigned PY_LONG_LONG) (((((((unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0]));
                    if (8 * sizeof(unsigned PY_LONG_LONG) > 3 * PyLong_SHIFT) {
                            __PYX_VERIFY_RETURN_INT(unsigned PY_LONG_LONG, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                        } else if (8 * sizeof(unsigned PY_LONG_LONG) >= 4 * PyLong_SHIFT) {
                            return (unsigned PY_LONG_LONG) (((((((((unsigned PY_LONG_LONG)digits[3]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0]));
                    return (unsigned PY_LONG_LONG) -1;
            if (sizeof(unsigned PY_LONG_LONG) <= sizeof(unsigned long)) {
                __PYX_VERIFY_RETURN_INT_EXC(unsigned PY_LONG_LONG, unsigned long, PyLong_AsUnsignedLong(x))
            } else if (sizeof(unsigned PY_LONG_LONG) <= sizeof(unsigned PY_LONG_LONG)) {
                __PYX_VERIFY_RETURN_INT_EXC(unsigned PY_LONG_LONG, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x))
                case  0: return (unsigned PY_LONG_LONG) 0;
                case -1: __PYX_VERIFY_RETURN_INT(unsigned PY_LONG_LONG, sdigit, (sdigit) (-(sdigit)digits[0]))
                case  1: __PYX_VERIFY_RETURN_INT(unsigned PY_LONG_LONG,  digit, +digits[0])
                    if (8 * sizeof(unsigned PY_LONG_LONG) - 1 > 1 * PyLong_SHIFT) {
                            __PYX_VERIFY_RETURN_INT(unsigned PY_LONG_LONG, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                        } else if (8 * sizeof(unsigned PY_LONG_LONG) - 1 > 2 * PyLong_SHIFT) {
                            return (unsigned PY_LONG_LONG) (((unsigned PY_LONG_LONG)-1)*(((((unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])));
                    if (8 * sizeof(unsigned PY_LONG_LONG) > 1 * PyLong_SHIFT) {
                            __PYX_VERIFY_RETURN_INT(unsigned PY_LONG_LONG, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                        } else if (8 * sizeof(unsigned PY_LONG_LONG) - 1 > 2 * PyLong_SHIFT) {
                            return (unsigned PY_LONG_LONG) ((((((unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])));
                    if (8 * sizeof(unsigned PY_LONG_LONG) - 1 > 2 * PyLong_SHIFT) {
                            __PYX_VERIFY_RETURN_INT(unsigned PY_LONG_LONG, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                        } else if (8 * sizeof(unsigned PY_LONG_LONG) - 1 > 3 * PyLong_SHIFT) {
                            return (unsigned PY_LONG_LONG) (((unsigned PY_LONG_LONG)-1)*(((((((unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])));
                    if (8 * sizeof(unsigned PY_LONG_LONG) > 2 * PyLong_SHIFT) {
                            __PYX_VERIFY_RETURN_INT(unsigned PY_LONG_LONG, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                        } else if (8 * sizeof(unsigned PY_LONG_LONG) - 1 > 3 * PyLong_SHIFT) {
                            return (unsigned PY_LONG_LONG) ((((((((unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])));
                    if (8 * sizeof(unsigned PY_LONG_LONG) - 1 > 3 * PyLong_SHIFT) {
                            __PYX_VERIFY_RETURN_INT(unsigned PY_LONG_LONG, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                        } else if (8 * sizeof(unsigned PY_LONG_LONG) - 1 > 4 * PyLong_SHIFT) {
                            return (unsigned PY_LONG_LONG) (((unsigned PY_LONG_LONG)-1)*(((((((((unsigned PY_LONG_LONG)digits[3]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])));
                    if (8 * sizeof(unsigned PY_LONG_LONG) > 3 * PyLong_SHIFT) {
                            __PYX_VERIFY_RETURN_INT(unsigned PY_LONG_LONG, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                        } else if (8 * sizeof(unsigned PY_LONG_LONG) - 1 > 4 * PyLong_SHIFT) {
                            return (unsigned PY_LONG_LONG) ((((((((((unsigned PY_LONG_LONG)digits[3]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])));
            if (sizeof(unsigned PY_LONG_LONG) <= sizeof(long)) {
                __PYX_VERIFY_RETURN_INT_EXC(unsigned PY_LONG_LONG, long, PyLong_AsLong(x))
            } else if (sizeof(unsigned PY_LONG_LONG) <= sizeof(PY_LONG_LONG)) {
                __PYX_VERIFY_RETURN_INT_EXC(unsigned PY_LONG_LONG, PY_LONG_LONG, PyLong_AsLongLong(x))
            unsigned PY_LONG_LONG val;
            return (unsigned PY_LONG_LONG) -1;
        unsigned PY_LONG_LONG val;
        if (!tmp) return (unsigned PY_LONG_LONG) -1;
        val = __Pyx_PyInt_As_unsigned_PY_LONG_LONG(tmp);
        "value too large to convert to unsigned PY_LONG_LONG");
    return (unsigned PY_LONG_LONG) -1;
        "can't convert negative value to unsigned PY_LONG_LONG");
    return (unsigned PY_LONG_LONG) -1;
def write_varint(unsigned long long number, buf):
    cdef unsigned char to_write, i = 0
    # unsigned PY_LONG_LONG checks integer on function call and
    # raises OverflowError if integer overflows unsigned PY_LONG_LONG.
    # Long enough for handling unsigned PY_LONG_LONG.
        to_write = number & 0x7f
            num_buf[i] = to_write | 0x80
            num_buf[i] = to_write
    cdef unsigned char shift = 0
    cdef unsigned long long i, result = 0
from io import BytesIO
from unittest import TestCase

from clickhouse_driver.varint import read_varint, write_varint


class VarIntTestCase(TestCase):
    def test_check_not_negative(self):
        n = 0x9FFFFFFF

        buf = BytesIO()
        write_varint(n, buf)
        val = buf.getvalue()
        self.assertEqual(b'\xFF\xFF\xFF\xFF\t', val)

        buf = BytesIO(val)
        buf.read_one = lambda: ord(buf.read(1))
        m = read_varint(buf)
        self.assertEqual(m, n)