Merge in touch.
[awesomized/libmemcached] / libmemcached / version.cc
index abb720054545177ba929e3342c24675bafba8da0..b70cf672278c7421257ab9cacdd3269e071454bd 100644 (file)
@@ -46,88 +46,100 @@ static inline memcached_return_t memcached_version_textual(memcached_st *ptr);
 
 memcached_return_t memcached_version(memcached_st *ptr)
 {
+  memcached_return_t rc;
+  if (memcached_failed(rc= initialize_query(ptr)))
+  {
+    return rc;
+  }
+
   if (ptr->flags.use_udp)
+  {
     return MEMCACHED_NOT_SUPPORTED;
-
-  memcached_return_t rc;
+  }
 
   if (ptr->flags.binary_protocol)
+  {
     rc= memcached_version_binary(ptr);
+  }
   else
+  {
     rc= memcached_version_textual(ptr);      
+  }
 
   return rc;
 }
 
 static inline memcached_return_t memcached_version_textual(memcached_st *ptr)
 {
-  size_t send_length;
-  memcached_return_t rc;
-  char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-  char *response_ptr;
-  const char *command= "version\r\n";
-
-  send_length= sizeof("version\r\n") -1;
-
-  rc= MEMCACHED_SUCCESS;
+  memcached_return_t rc= MEMCACHED_SUCCESS;
   for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
   {
-    memcached_return_t rrc;
-    memcached_server_write_instance_st instance=
-      memcached_server_instance_fetch(ptr, x);
+    memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, x);
 
     // Optimization, we only fetch version once.
     if (instance->major_version != UINT8_MAX)
+    {
       continue;
+    }
 
-    rrc= memcached_do(instance, command, send_length, true);
-    if (rrc != MEMCACHED_SUCCESS)
+    memcached_return_t rrc= memcached_do(instance, memcached_literal_param("version\r\n"), true);
+    if (memcached_failed(rrc))
     {
+      (void)memcached_set_error(*instance, rrc, MEMCACHED_AT);
       instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
       rc= MEMCACHED_SOME_ERRORS;
       continue;
     }
 
+    char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
     rrc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
-    if (rrc != MEMCACHED_SUCCESS)
+    if (memcached_failed(rrc))
     {
+      memcached_set_error(*instance, rrc, MEMCACHED_AT);
       instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
       rc= MEMCACHED_SOME_ERRORS;
       continue;
     }
 
     /* Find the space, and then move one past it to copy version */
-    response_ptr= index(buffer, ' ');
+    char *response_ptr= index(buffer, ' ');
     response_ptr++;
 
-    instance->major_version= (uint8_t)strtol(response_ptr, (char **)NULL, 10);
-    if (errno == ERANGE)
+    long int version= strtol(response_ptr, (char **)NULL, 10);
+    if (version == LONG_MIN or version == LONG_MAX or errno == EINVAL or version > UINT8_MAX or version == 0)
     {
+      memcached_set_error(*instance, MEMCACHED_PROTOCOL_ERROR, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse major version"));
       instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
       rc= MEMCACHED_SOME_ERRORS;
       continue;
     }
+    instance->major_version= uint8_t(version);
 
     response_ptr= index(response_ptr, '.');
     response_ptr++;
 
-    instance->minor_version= (uint8_t)strtol(response_ptr, (char **)NULL, 10);
-    if (errno == ERANGE)
+    version= strtol(response_ptr, (char **)NULL, 10);
+    if (version == LONG_MIN or version == LONG_MAX or errno == EINVAL or version > UINT8_MAX)
     {
+      memcached_set_error(*instance, MEMCACHED_PROTOCOL_ERROR, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse minor version"));
       instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
       rc= MEMCACHED_SOME_ERRORS;
       continue;
     }
+    instance->minor_version= uint8_t(version);
 
     response_ptr= index(response_ptr, '.');
     response_ptr++;
-    instance->micro_version= (uint8_t)strtol(response_ptr, (char **)NULL, 10);
-    if (errno == ERANGE)
+
+    version= strtol(response_ptr, (char **)NULL, 10);
+    if (version == LONG_MIN or version == LONG_MAX or errno == EINVAL or version > UINT8_MAX)
     {
+      memcached_set_error(*instance, MEMCACHED_PROTOCOL_ERROR, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse micro version"));
       instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
       rc= MEMCACHED_SOME_ERRORS;
       continue;
     }
+    instance->micro_version= uint8_t(version);
   }
 
   return rc;
@@ -135,25 +147,23 @@ static inline memcached_return_t memcached_version_textual(memcached_st *ptr)
 
 static inline memcached_return_t memcached_version_binary(memcached_st *ptr)
 {
-  memcached_return_t rc;
   protocol_binary_request_version request= {};
   request.message.header.request.magic= PROTOCOL_BINARY_REQ;
   request.message.header.request.opcode= PROTOCOL_BINARY_CMD_VERSION;
   request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
 
-  rc= MEMCACHED_SUCCESS;
+  memcached_return_t rc= MEMCACHED_SUCCESS;
   for (uint32_t x= 0; x < memcached_server_count(ptr); x++) 
   {
-    memcached_return_t rrc;
-
-    memcached_server_write_instance_st instance=
-      memcached_server_instance_fetch(ptr, x);
+    memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, x);
 
     if (instance->major_version != UINT8_MAX)
+    {
       continue;
+    }
 
-    rrc= memcached_do(instance, request.bytes, sizeof(request.bytes), true);
-    if (rrc != MEMCACHED_SUCCESS) 
+    memcached_return_t rrc= memcached_do(instance, request.bytes, sizeof(request.bytes), true);
+    if (memcached_failed(rrc))
     {
       memcached_io_reset(instance);
       rc= MEMCACHED_SOME_ERRORS;
@@ -167,46 +177,52 @@ static inline memcached_return_t memcached_version_binary(memcached_st *ptr)
       memcached_server_instance_fetch(ptr, x);
 
     if (instance->major_version != UINT8_MAX)
+    {
       continue;
+    }
 
     if (memcached_server_response_count(instance) > 0) 
     {
-      memcached_return_t rrc;
       char buffer[32];
       char *p;
 
-      rrc= memcached_response(instance, buffer, sizeof(buffer), NULL);
-      if (rrc != MEMCACHED_SUCCESS) 
+      memcached_return_t rrc= memcached_response(instance, buffer, sizeof(buffer), NULL);
+      if (memcached_failed(rrc))
       {
         memcached_io_reset(instance);
         rc= MEMCACHED_SOME_ERRORS;
         continue;
       }
 
-      instance->major_version= (uint8_t)strtol(buffer, &p, 10);
-      if (errno == ERANGE)
+      long int version= strtol(buffer, &p, 10);
+      if (version == LONG_MIN or version == LONG_MAX or errno == EINVAL or version > UINT8_MAX or version == 0)
       {
+        memcached_set_error(*instance, MEMCACHED_PROTOCOL_ERROR, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse major version"));
         instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
         rc= MEMCACHED_SOME_ERRORS;
         continue;
       }
+      instance->major_version= uint8_t(version);
 
-      instance->minor_version= (uint8_t)strtol(p + 1, &p, 10);
-      if (errno == ERANGE)
+      version= strtol(p +1, &p, 10);
+      if (version == LONG_MIN or version == LONG_MAX or errno == EINVAL or version > UINT8_MAX)
       {
+        memcached_set_error(*instance, MEMCACHED_PROTOCOL_ERROR, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse micro version"));
         instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
         rc= MEMCACHED_SOME_ERRORS;
         continue;
       }
+      instance->minor_version= uint8_t(version);
 
-      instance->micro_version= (uint8_t)strtol(p + 1, NULL, 10);
+      version= strtol(p + 1, NULL, 10);
       if (errno == ERANGE)
       {
+        memcached_set_error(*instance, MEMCACHED_PROTOCOL_ERROR, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse micro version"));
         instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
         rc= MEMCACHED_SOME_ERRORS;
         continue;
       }
-
+      instance->micro_version= uint8_t(version);
     }
   }