Initial commit
[hashcat.git] / src / shared.c
index 71f5972..3feb053 100644 (file)
@@ -1,18 +1,17 @@
 /**
- * Author......: Jens Steube <jens.steube@gmail.com>
+ * Authors.....: Jens Steube <jens.steube@gmail.com>
+ *               Gabriele Gristina <matrix@hashcat.net>
+ *
  * License.....: MIT
  */
 
+#ifdef OSX
+#include <stdio.h>
+#endif
+
 #include <shared.h>
 #include <limits.h>
 
-/**
- * tuning tools
- */
-
-#define GET_ACCEL(x) KERNEL_ACCEL_ ## x
-#define GET_LOOPS(x) KERNEL_LOOPS_ ## x
-
 /**
  * basic bit handling
  */
@@ -91,7 +90,7 @@ void log_final (FILE *fp, const char *fmt, va_list ap)
     fputc ('\r', fp);
   }
 
-  char s[4096];
+  char s[4096] = { 0 };
 
   int max_len = (int) sizeof (s);
 
@@ -448,13 +447,13 @@ int base32_encode (u8 (*f) (const u8), const u8 *in_buf, int in_len, u8 *out_buf
     out_ptr += 8;
   }
 
-  int out_len = (in_len * 8) / 5;
+  int out_len = (int) (((0.5 + (float) in_len) * 8) / 5); // ceil (in_len * 8 / 5)
 
-  for (int i = 0; i < (7 - (in_len % 7)); i++)
+  while (out_len % 8)
   {
-    out_len++;
-
     out_buf[out_len] = '=';
+
+    out_len++;
   }
 
   return out_len;
@@ -515,13 +514,13 @@ int base64_encode (u8 (*f) (const u8), const u8 *in_buf, int in_len, u8 *out_buf
     out_ptr += 4;
   }
 
-  int out_len = (in_len * 8) / 6;
+  int out_len = (int) (((0.5 + (float) in_len) * 8) / 6); // ceil (in_len * 8 / 6)
 
-  for (int i = 0; i < (3 - (in_len % 3)); i++)
+  while (out_len % 4)
   {
-    out_len++;
-
     out_buf[out_len] = '=';
+
+    out_len++;
   }
 
   return out_len;
@@ -624,7 +623,7 @@ static void AES128_decrypt_cbc (const u32 key[4], const u32 iv[4], const u32 in[
 
   AES_set_decrypt_key ((const u8 *) key, 128, &skey);
 
-  u32 _iv[4];
+  u32 _iv[4] = { 0 };
 
   _iv[0] = iv[0];
   _iv[1] = iv[1];
@@ -633,8 +632,8 @@ static void AES128_decrypt_cbc (const u32 key[4], const u32 iv[4], const u32 in[
 
   for (int i = 0; i < 16; i += 4)
   {
-    u32 _in[4];
-    u32 _out[4];
+    u32 _in[4] = { 0 };
+    u32 _out[4] = { 0 };
 
     _in[0] = in[i + 0];
     _in[1] = in[i + 1];
@@ -664,9 +663,7 @@ static void juniper_decrypt_hash (char *in, char *out)
 {
   // base64 decode
 
-  u8 base64_buf[100];
-
-  memset (base64_buf, 0, sizeof (base64_buf));
+  u8 base64_buf[100] = { 0 };
 
   base64_decode (base64_to_int, (const u8 *) in, DISPLAY_LEN_MIN_501, base64_buf);
 
@@ -680,7 +677,7 @@ static void juniper_decrypt_hash (char *in, char *out)
 
   // reversed key
 
-  u32 juniper_key[4];
+  u32 juniper_key[4] = { 0 };
 
   juniper_key[0] = byte_swap_32 (0xa6707a7e);
   juniper_key[1] = byte_swap_32 (0x8df91059);
@@ -2446,6 +2443,8 @@ int tty_getchar()
 
   DWORD num = 0;
 
+  memset (buf, 0, sizeof (buf));
+
   ReadConsoleInput (stdinHandle, buf, 100, &num);
 
   FlushConsoleInputBuffer (stdinHandle);
@@ -2601,7 +2600,7 @@ char *logfile_generate_topid ()
 
   char *topid = (char *) mymalloc (1 + 16 + 1);
 
-  sprintf (topid, "TOP%08x", id);
+  snprintf (topid, 1 + 16, "TOP%08x", id);
 
   return topid;
 }
@@ -2612,7 +2611,7 @@ char *logfile_generate_subid ()
 
   char *subid = (char *) mymalloc (1 + 16 + 1);
 
-  sprintf (subid, "SUB%08x", id);
+  snprintf (subid, 1 + 16, "SUB%08x", id);
 
   return subid;
 }
@@ -2621,6 +2620,36 @@ char *logfile_generate_subid ()
  * system
  */
 
+#if F_SETLKW
+void lock_file (FILE *fp)
+{
+  struct flock lock;
+
+  memset (&lock, 0, sizeof (struct flock));
+
+  lock.l_type = F_WRLCK;
+  while (fcntl(fileno(fp), F_SETLKW, &lock))
+  {
+    if (errno != EINTR)
+    {
+      log_error ("ERROR: failed acquiring write lock: %s", strerror (errno));
+
+      exit (-1);
+    }
+  }
+}
+
+void unlock_file (FILE *fp)
+{
+  struct flock lock;
+
+  memset (&lock, 0, sizeof (struct flock));
+
+  lock.l_type = F_UNLCK;
+  fcntl(fileno(fp), F_SETLK, &lock);
+}
+#endif // F_SETLKW
+
 #ifdef _WIN
 void fsync (int fd)
 {
@@ -2634,12 +2663,13 @@ void fsync (int fd)
  * thermal
  */
 
-#ifdef _WIN
+#ifdef HAVE_HWMON
+#if defined(_WIN) && defined(HAVE_NVAPI)
 int hm_get_adapter_index_nv (HM_ADAPTER_NV nvGPUHandle[DEVICES_MAX])
 {
   NvU32 pGpuCount;
 
-  if (hc_NvAPI_EnumPhysicalGPUs (nvGPUHandle, &pGpuCount) != NVAPI_OK) return (0);
+  if (hm_NvAPI_EnumPhysicalGPUs (data.hm_nv, nvGPUHandle, &pGpuCount) != NVAPI_OK) return (0);
 
   if (pGpuCount == 0)
   {
@@ -2650,20 +2680,20 @@ int hm_get_adapter_index_nv (HM_ADAPTER_NV nvGPUHandle[DEVICES_MAX])
 
   return (pGpuCount);
 }
-#endif
+#endif // _WIN && HAVE_NVAPI
 
-#ifdef LINUX
+#if defined(LINUX) && defined(HAVE_NVML)
 int hm_get_adapter_index_nv (HM_ADAPTER_NV nvGPUHandle[DEVICES_MAX])
 {
   int pGpuCount = 0;
 
   for (uint i = 0; i < DEVICES_MAX; i++)
   {
-    if (hc_NVML_nvmlDeviceGetHandleByIndex (data.hm_dll_nv, 1, i, &nvGPUHandle[i]) != NVML_SUCCESS) break;
+    if (hm_NVML_nvmlDeviceGetHandleByIndex (data.hm_nv, 1, i, &nvGPUHandle[i]) != NVML_SUCCESS) break;
 
     // can be used to determine if the device by index matches the cuda device by index
     // char name[100]; memset (name, 0, sizeof (name));
-    // hc_NVML_nvmlDeviceGetName (data.hm_dll_nv, nvGPUHandle[i], name, sizeof (name) - 1);
+    // hm_NVML_nvmlDeviceGetName (data.hm_nv, nvGPUHandle[i], name, sizeof (name) - 1);
 
     pGpuCount++;
   }
@@ -2677,52 +2707,12 @@ int hm_get_adapter_index_nv (HM_ADAPTER_NV nvGPUHandle[DEVICES_MAX])
 
   return (pGpuCount);
 }
-#endif
-
-void hm_close (HM_LIB hm_dll)
-{
-  #ifdef _POSIX
-  dlclose (hm_dll);
-
-  #elif _WIN
-  FreeLibrary (hm_dll);
-
-  #endif
-}
-
-HM_LIB hm_init (const cl_uint vendor_id)
-{
-  HM_LIB hm_dll = NULL;
-
-  if (vendor_id == VENDOR_ID_AMD)
-  {
-    #ifdef _POSIX
-    hm_dll = dlopen ("libatiadlxx.so", RTLD_LAZY | RTLD_GLOBAL);
-
-    #elif _WIN
-    hm_dll = LoadLibrary ("atiadlxx.dll");
-
-    if (hm_dll == NULL)
-    {
-      hm_dll = LoadLibrary ("atiadlxy.dll");
-    }
-
-    #endif
-  }
-
-  #ifdef LINUX
-  if (vendor_id == VENDOR_ID_NV)
-  {
-    hm_dll = dlopen ("libnvidia-ml.so", RTLD_LAZY | RTLD_GLOBAL);
-  }
-  #endif
-
-  return hm_dll;
-}
+#endif // LINUX && HAVE_NVML
 
-int get_adapters_num_amd (HM_LIB hm_dll_amd, int *iNumberAdapters)
+#ifdef HAVE_ADL
+int get_adapters_num_amd (void *adl, int *iNumberAdapters)
 {
-  if (hc_ADL_Adapter_NumberOfAdapters_Get (hm_dll_amd, iNumberAdapters) != ADL_OK) return -1;
+  if (hm_ADL_Adapter_NumberOfAdapters_Get ((ADL_PTR *) adl, iNumberAdapters) != ADL_OK) return -1;
 
   if (iNumberAdapters == 0)
   {
@@ -2743,7 +2733,7 @@ int hm_show_performance_level (HM_LIB hm_dll, int iAdapterIndex)
   lpOdParameters.iSize = sizeof (ADLODParameters);
   size_t plevels_size = 0;
 
-  if (hc_ADL_Overdrive_ODParameters_Get (hm_dll, iAdapterIndex, &lpOdParameters) != ADL_OK) return -1;
+  if (hm_ADL_Overdrive_ODParameters_Get (hm_dll, iAdapterIndex, &lpOdParameters) != ADL_OK) return -1;
 
   log_info ("[DEBUG] %s, adapter %d performance level (%d) : %s %s",
           __func__, iAdapterIndex,
@@ -2757,7 +2747,7 @@ int hm_show_performance_level (HM_LIB hm_dll, int iAdapterIndex)
 
   lpOdPerformanceLevels->iSize = sizeof (ADLODPerformanceLevels) + sizeof (ADLODPerformanceLevel) * (lpOdParameters.iNumberOfPerformanceLevels - 1);
 
-  if (hc_ADL_Overdrive_ODPerformanceLevels_Get (hm_dll, iAdapterIndex, 0, lpOdPerformanceLevels) != ADL_OK) return -1;
+  if (hm_ADL_Overdrive_ODPerformanceLevels_Get (hm_dll, iAdapterIndex, 0, lpOdPerformanceLevels) != ADL_OK) return -1;
 
   for (int j = 0; j < lpOdParameters.iNumberOfPerformanceLevels; j++)
     log_info ("[DEBUG] %s, adapter %d, level %d : engine %d, memory %d, voltage: %d",
@@ -2770,13 +2760,13 @@ int hm_show_performance_level (HM_LIB hm_dll, int iAdapterIndex)
 }
 */
 
-LPAdapterInfo hm_get_adapter_info_amd (HM_LIB hm_dll_amd, int iNumberAdapters)
+LPAdapterInfo hm_get_adapter_info_amd (void *adl, int iNumberAdapters)
 {
   size_t AdapterInfoSize = iNumberAdapters * sizeof (AdapterInfo);
 
   LPAdapterInfo lpAdapterInfo = (LPAdapterInfo) mymalloc (AdapterInfoSize);
 
-  if (hc_ADL_Adapter_AdapterInfo_Get (hm_dll_amd, lpAdapterInfo, AdapterInfoSize) != ADL_OK) return NULL;
+  if (hm_ADL_Adapter_AdapterInfo_Get ((ADL_PTR *) adl, lpAdapterInfo, AdapterInfoSize) != ADL_OK) return NULL;
 
   return lpAdapterInfo;
 }
@@ -2935,7 +2925,7 @@ u32 *hm_get_list_valid_adl_adapters (int iNumberAdapters, int *num_adl_adapters,
   return adl_adapters;
 }
 
-int hm_check_fanspeed_control (HM_LIB hm_dll_amd, hm_attrs_t *hm_device, u32 *valid_adl_device_list, int num_adl_adapters, LPAdapterInfo lpAdapterInfo)
+int hm_check_fanspeed_control (void *adl, hm_attrs_t *hm_device, u32 *valid_adl_device_list, int num_adl_adapters, LPAdapterInfo lpAdapterInfo)
 {
   // loop through all valid devices
 
@@ -2953,7 +2943,7 @@ int hm_check_fanspeed_control (HM_LIB hm_dll_amd, hm_attrs_t *hm_device, u32 *va
 
     int opencl_device_index = i;
 
-    // if (hm_show_performance_level (hm_dll_amd, info.iAdapterIndex) != 0) return -1;
+    // if (hm_show_performance_level (adl, info.iAdapterIndex) != 0) return -1;
 
     // get fanspeed info
 
@@ -2965,7 +2955,7 @@ int hm_check_fanspeed_control (HM_LIB hm_dll_amd, hm_attrs_t *hm_device, u32 *va
 
       FanSpeedInfo.iSize = sizeof (ADLFanSpeedInfo);
 
-      if (hc_ADL_Overdrive5_FanSpeedInfo_Get (hm_dll_amd, info.iAdapterIndex, 0, &FanSpeedInfo) != ADL_OK) return -1;
+      if (hm_ADL_Overdrive5_FanSpeedInfo_Get (adl, info.iAdapterIndex, 0, &FanSpeedInfo) != ADL_OK) return -1;
 
       // check read and write capability in fanspeedinfo
 
@@ -2985,7 +2975,7 @@ int hm_check_fanspeed_control (HM_LIB hm_dll_amd, hm_attrs_t *hm_device, u32 *va
 
       memset (&faninfo, 0, sizeof (faninfo));
 
-      if (hc_ADL_Overdrive6_FanSpeed_Get (hm_dll_amd, info.iAdapterIndex, &faninfo) != ADL_OK) return -1;
+      if (hm_ADL_Overdrive6_FanSpeed_Get (adl, info.iAdapterIndex, &faninfo) != ADL_OK) return -1;
 
       // check read capability in fanspeedinfo
 
@@ -3003,7 +2993,7 @@ int hm_check_fanspeed_control (HM_LIB hm_dll_amd, hm_attrs_t *hm_device, u32 *va
   return 0;
 }
 
-int hm_get_overdrive_version (HM_LIB hm_dll_amd, hm_attrs_t *hm_device, u32 *valid_adl_device_list, int num_adl_adapters, LPAdapterInfo lpAdapterInfo)
+int hm_get_overdrive_version (void *adl, hm_attrs_t *hm_device, u32 *valid_adl_device_list, int num_adl_adapters, LPAdapterInfo lpAdapterInfo)
 {
   for (int i = 0; i < num_adl_adapters; i++)
   {
@@ -3019,7 +3009,7 @@ int hm_get_overdrive_version (HM_LIB hm_dll_amd, hm_attrs_t *hm_device, u32 *val
     int od_enabled   = 0;
     int od_version   = 0;
 
-    if (hc_ADL_Overdrive_Caps (hm_dll_amd, info.iAdapterIndex, &od_supported, &od_enabled, &od_version) != ADL_OK) return -1;
+    if (hm_ADL_Overdrive_Caps (adl, info.iAdapterIndex, &od_supported, &od_enabled, &od_version) != ADL_OK) return -1;
 
     // store the overdrive version in hm_device
 
@@ -3058,14 +3048,16 @@ int hm_get_adapter_index_amd (hm_attrs_t *hm_device, u32 *valid_adl_device_list,
 
   return num_adl_adapters;
 }
+#endif // HAVE_ADL
 
 int hm_get_temperature_with_device_id (const uint device_id)
 {
   if ((data.devices_param[device_id].device_type & CL_DEVICE_TYPE_GPU) == 0) return -1;
 
+  #ifdef HAVE_ADL
   if (data.devices_param[device_id].vendor_id == VENDOR_ID_AMD)
   {
-    if (data.hm_dll_amd)
+    if (data.hm_amd)
     {
       if (data.hm_device[device_id].od_version == 5)
       {
@@ -3073,7 +3065,7 @@ int hm_get_temperature_with_device_id (const uint device_id)
 
         Temperature.iSize = sizeof (ADLTemperature);
 
-        if (hc_ADL_Overdrive5_Temperature_Get (data.hm_dll_amd, data.hm_device[device_id].adapter_index.amd, 0, &Temperature) != ADL_OK) return -1;
+        if (hm_ADL_Overdrive5_Temperature_Get (data.hm_amd, data.hm_device[device_id].adapter_index.amd, 0, &Temperature) != ADL_OK) return -1;
 
         return Temperature.iTemperature / 1000;
       }
@@ -3081,23 +3073,26 @@ int hm_get_temperature_with_device_id (const uint device_id)
       {
         int Temperature = 0;
 
-        if (hc_ADL_Overdrive6_Temperature_Get (data.hm_dll_amd, data.hm_device[device_id].adapter_index.amd, &Temperature) != ADL_OK) return -1;
+        if (hm_ADL_Overdrive6_Temperature_Get (data.hm_amd, data.hm_device[device_id].adapter_index.amd, &Temperature) != ADL_OK) return -1;
 
         return Temperature / 1000;
       }
     }
   }
-  else if (data.devices_param[device_id].vendor_id == VENDOR_ID_NV)
+  #endif
+
+  #if defined(HAVE_NVML) || defined(HAVE_NVAPI)
+  if (data.devices_param[device_id].vendor_id == VENDOR_ID_NV)
   {
-    #ifdef LINUX
+    #if defined(LINUX) && defined(HAVE_NVML)
     int temperature = 0;
 
-    hc_NVML_nvmlDeviceGetTemperature (data.hm_dll_nv, data.hm_device[device_id].adapter_index.nv, NVML_TEMPERATURE_GPU, (unsigned int *) &temperature);
+    hm_NVML_nvmlDeviceGetTemperature (data.hm_nv, data.hm_device[device_id].adapter_index.nv, NVML_TEMPERATURE_GPU, (unsigned int *) &temperature);
 
     return temperature;
     #endif
 
-    #ifdef WIN
+    #if defined(WIN) && defined(HAVE_NVAPI)
     NV_GPU_THERMAL_SETTINGS pThermalSettings;
 
     pThermalSettings.version = NV_GPU_THERMAL_SETTINGS_VER;
@@ -3105,11 +3100,12 @@ int hm_get_temperature_with_device_id (const uint device_id)
     pThermalSettings.sensor[0].controller = NVAPI_THERMAL_CONTROLLER_UNKNOWN;
     pThermalSettings.sensor[0].target = NVAPI_THERMAL_TARGET_GPU;
 
-    if (hc_NvAPI_GPU_GetThermalSettings (data.hm_device[device_id].adapter_index.nv, 0, &pThermalSettings) != NVAPI_OK) return -1;
+    if (hm_NvAPI_GPU_GetThermalSettings (data.hm_nv, data.hm_device[device_id].adapter_index.nv, 0, &pThermalSettings) != NVAPI_OK) return -1;
 
     return pThermalSettings.sensor[0].currentTemp;
-    #endif
+    #endif // WIN && HAVE_NVAPI
   }
+  #endif // HAVE_NVML || HAVE_NVAPI
 
   return -1;
 }
@@ -3121,9 +3117,10 @@ int hm_get_fanspeed_with_device_id (const uint device_id)
 
   if (data.hm_device[device_id].fan_supported == 1)
   {
+    #ifdef HAVE_ADL
     if (data.devices_param[device_id].vendor_id == VENDOR_ID_AMD)
     {
-      if (data.hm_dll_amd)
+      if (data.hm_amd)
       {
         if (data.hm_device[device_id].od_version == 5)
         {
@@ -3135,7 +3132,7 @@ int hm_get_fanspeed_with_device_id (const uint device_id)
           lpFanSpeedValue.iSpeedType = ADL_DL_FANCTRL_SPEED_TYPE_PERCENT;
           lpFanSpeedValue.iFlags     = ADL_DL_FANCTRL_FLAG_USER_DEFINED_SPEED;
 
-          if (hc_ADL_Overdrive5_FanSpeed_Get (data.hm_dll_amd, data.hm_device[device_id].adapter_index.amd, 0, &lpFanSpeedValue) != ADL_OK) return -1;
+          if (hm_ADL_Overdrive5_FanSpeed_Get (data.hm_amd, data.hm_device[device_id].adapter_index.amd, 0, &lpFanSpeedValue) != ADL_OK) return -1;
 
           return lpFanSpeedValue.iFanSpeed;
         }
@@ -3145,30 +3142,37 @@ int hm_get_fanspeed_with_device_id (const uint device_id)
 
           memset (&faninfo, 0, sizeof (faninfo));
 
-          if (hc_ADL_Overdrive6_FanSpeed_Get (data.hm_dll_amd, data.hm_device[device_id].adapter_index.amd, &faninfo) != ADL_OK) return -1;
+          if (hm_ADL_Overdrive6_FanSpeed_Get (data.hm_amd, data.hm_device[device_id].adapter_index.amd, &faninfo) != ADL_OK) return -1;
 
           return faninfo.iFanSpeedPercent;
         }
       }
     }
-    else if (data.devices_param[device_id].vendor_id == VENDOR_ID_NV)
+    #endif // HAVE_ADL
+
+    #if defined(HAVE_NVML) || defined(HAVE_NVAPI)
+    if (data.devices_param[device_id].vendor_id == VENDOR_ID_NV)
     {
-      #ifdef LINUX
+      #if defined(LINUX) && defined(HAVE_NVML)
       int speed = 0;
 
-      hc_NVML_nvmlDeviceGetFanSpeed (data.hm_dll_nv, 1, data.hm_device[device_id].adapter_index.nv, (unsigned int *) &speed);
+      hm_NVML_nvmlDeviceGetFanSpeed (data.hm_nv, 1, data.hm_device[device_id].adapter_index.nv, (unsigned int *) &speed);
 
       return speed;
       #endif
 
-      #ifdef WIN
-      NvU32 speed = 0;
+      #if defined(WIN) && defined(HAVE_NVAPI)
 
-      hc_NvAPI_GPU_GetTachReading (data.hm_device[device_id].adapter_index.nv, &speed);
+      NV_GPU_COOLER_SETTINGS pCoolerSettings;
 
-      return speed;
+      pCoolerSettings.Version = GPU_COOLER_SETTINGS_VER | sizeof (NV_GPU_COOLER_SETTINGS);
+
+      hm_NvAPI_GPU_GetCoolerSettings (data.hm_nv, data.hm_device[device_id].adapter_index.nv, 0, &pCoolerSettings);
+
+      return pCoolerSettings.Cooler[0].CurrentLevel;
       #endif
     }
+    #endif // HAVE_NVML || HAVE_NVAPI
   }
 
   return -1;
@@ -3178,48 +3182,54 @@ int hm_get_utilization_with_device_id (const uint device_id)
 {
   if ((data.devices_param[device_id].device_type & CL_DEVICE_TYPE_GPU) == 0) return -1;
 
+  #ifdef HAVE_ADL
   if (data.devices_param[device_id].vendor_id == VENDOR_ID_AMD)
   {
-    if (data.hm_dll_amd)
+    if (data.hm_amd)
     {
       ADLPMActivity PMActivity;
 
       PMActivity.iSize = sizeof (ADLPMActivity);
 
-      if (hc_ADL_Overdrive_CurrentActivity_Get (data.hm_dll_amd, data.hm_device[device_id].adapter_index.amd, &PMActivity) != ADL_OK) return -1;
+      if (hm_ADL_Overdrive_CurrentActivity_Get (data.hm_amd, data.hm_device[device_id].adapter_index.amd, &PMActivity) != ADL_OK) return -1;
 
       return PMActivity.iActivityPercent;
     }
   }
-  else if (data.devices_param[device_id].vendor_id == VENDOR_ID_NV)
+  #endif // HAVE_ADL
+
+  #if defined(HAVE_NVML) || defined(HAVE_NVAPI)
+  if (data.devices_param[device_id].vendor_id == VENDOR_ID_NV)
   {
-    #ifdef LINUX
+    #if defined(LINUX) && defined(HAVE_NVML)
     nvmlUtilization_t utilization;
 
-    hc_NVML_nvmlDeviceGetUtilizationRates (data.hm_dll_nv, data.hm_device[device_id].adapter_index.nv, &utilization);
+    hm_NVML_nvmlDeviceGetUtilizationRates (data.hm_nv, data.hm_device[device_id].adapter_index.nv, &utilization);
 
     return utilization.gpu;
     #endif
 
-    #ifdef WIN
+    #if defined(WIN) && defined(HAVE_NVAPI)
     NV_GPU_DYNAMIC_PSTATES_INFO_EX pDynamicPstatesInfoEx;
 
     pDynamicPstatesInfoEx.version = NV_GPU_DYNAMIC_PSTATES_INFO_EX_VER;
 
-    if (hc_NvAPI_GPU_GetDynamicPstatesInfoEx (data.hm_device[device_id].adapter_index.nv, &pDynamicPstatesInfoEx) != NVAPI_OK) return -1;
+    if (hm_NvAPI_GPU_GetDynamicPstatesInfoEx (data.hm_nv, data.hm_device[device_id].adapter_index.nv, &pDynamicPstatesInfoEx) != NVAPI_OK) return -1;
 
     return pDynamicPstatesInfoEx.utilization[0].percentage;
     #endif
   }
+  #endif // HAVE_NVML || HAVE_NVAPI
 
   return -1;
 }
 
+#ifdef HAVE_ADL
 int hm_set_fanspeed_with_device_id_amd (const uint device_id, const int fanspeed)
 {
   if (data.hm_device[device_id].fan_supported == 1)
   {
-    if (data.hm_dll_amd)
+    if (data.hm_amd)
     {
       if (data.hm_device[device_id].od_version == 5)
       {
@@ -3232,7 +3242,7 @@ int hm_set_fanspeed_with_device_id_amd (const uint device_id, const int fanspeed
         lpFanSpeedValue.iFlags     = ADL_DL_FANCTRL_FLAG_USER_DEFINED_SPEED;
         lpFanSpeedValue.iFanSpeed  = fanspeed;
 
-        if (hc_ADL_Overdrive5_FanSpeed_Set (data.hm_dll_amd, data.hm_device[device_id].adapter_index.amd, 0, &lpFanSpeedValue) != ADL_OK) return -1;
+        if (hm_ADL_Overdrive5_FanSpeed_Set (data.hm_amd, data.hm_device[device_id].adapter_index.amd, 0, &lpFanSpeedValue) != ADL_OK) return -1;
 
         return 0;
       }
@@ -3245,7 +3255,7 @@ int hm_set_fanspeed_with_device_id_amd (const uint device_id, const int fanspeed
         fan_speed_value.iSpeedType = ADL_OD6_FANSPEED_TYPE_PERCENT;
         fan_speed_value.iFanSpeed  = fanspeed;
 
-        if (hc_ADL_Overdrive6_FanSpeed_Set (data.hm_dll_amd, data.hm_device[device_id].adapter_index.amd, &fan_speed_value) != ADL_OK) return -1;
+        if (hm_ADL_Overdrive6_FanSpeed_Set (data.hm_amd, data.hm_device[device_id].adapter_index.amd, &fan_speed_value) != ADL_OK) return -1;
 
         return 0;
       }
@@ -3254,6 +3264,7 @@ int hm_set_fanspeed_with_device_id_amd (const uint device_id, const int fanspeed
 
   return -1;
 }
+#endif
 
 // helper function for status display
 
@@ -3270,6 +3281,7 @@ void hm_device_val_to_str (char *target_buf, int max_buf_size, char *suffix, int
     snprintf (target_buf, max_buf_size, "%2d%s", value, suffix);
   }
 }
+#endif // HAVE_HWMON
 
 /**
  * maskprocessor
@@ -3310,8 +3322,6 @@ void mp_add_cs_buf (uint *in_buf, size_t in_len, cs_t *css, int css_cnt)
 
   uint *css_uniq = (uint *) mymalloc (css_uniq_sz);
 
-  memset (css_uniq, 0, css_uniq_sz);
-
   size_t i;
 
   for (i = 0; i < cs->cs_len; i++)
@@ -3575,9 +3585,7 @@ void mp_setup_sys (cs_t *mp_sys)
 {
   uint pos;
   uint chr;
-  uint donec[CHARSIZ];
-
-  memset (donec, 0, sizeof (donec));
+  uint donec[CHARSIZ] = { 0 };
 
   for (pos = 0, chr =  'a'; chr <=  'z'; chr++) { donec[chr] = 1;
                                                   mp_sys[0].cs_buf[pos++] = chr;
@@ -3612,9 +3620,7 @@ void mp_setup_usr (cs_t *mp_sys, cs_t *mp_usr, char *buf, uint index)
   }
   else
   {
-    char mp_file[1024];
-
-    memset (mp_file, 0, sizeof (mp_file));
+    char mp_file[1024] = { 0 };
 
     size_t len = fread (mp_file, 1, sizeof (mp_file) - 1, fp);
 
@@ -3796,9 +3802,7 @@ void sp_setup_tbl (const char *shared_dir, char *hcstat, uint disable, uint clas
 
   if (hcstat == NULL)
   {
-    char hcstat_tmp[256];
-
-    memset (hcstat_tmp, 0, sizeof (hcstat_tmp));
+    char hcstat_tmp[256] = { 0 };
 
     snprintf (hcstat_tmp, sizeof (hcstat_tmp) - 1, "%s/%s", shared_dir, SP_HCSTAT);
 
@@ -3818,6 +3822,8 @@ void sp_setup_tbl (const char *shared_dir, char *hcstat, uint disable, uint clas
   {
     log_error ("%s: Could not load data", hcstat);
 
+    fclose (fd);
+
     exit (-1);
   }
 
@@ -3825,6 +3831,8 @@ void sp_setup_tbl (const char *shared_dir, char *hcstat, uint disable, uint clas
   {
     log_error ("%s: Could not load data", hcstat);
 
+    fclose (fd);
+
     exit (-1);
   }
 
@@ -4099,18 +4107,31 @@ char *get_exec_path ()
 
   #ifdef LINUX
 
-  char tmp[32];
+  char tmp[32] = { 0 };
 
-  sprintf (tmp, "/proc/%d/exe", getpid ());
+  snprintf (tmp, sizeof (tmp) - 1, "/proc/%d/exe", getpid ());
 
   const int len = readlink (tmp, exec_path, exec_path_len - 1);
 
-  #endif
-
-  #ifdef WIN
+  #elif WIN
 
   const int len = GetModuleFileName (NULL, exec_path, exec_path_len - 1);
 
+  #elif OSX
+
+  uint size = exec_path_len;
+
+  if (_NSGetExecutablePath (exec_path, &size) != 0)
+  {
+    log_error("! executable path buffer too small\n");
+
+    exit (-1);
+  }
+
+  const int len = strlen (exec_path);
+
+  #else
+  #error Your Operating System is not supported or detected
   #endif
 
   exec_path[len] = 0;
@@ -4144,9 +4165,11 @@ char *get_profile_dir (const char *homedir)
 {
   #define DOT_HASHCAT ".hashcat"
 
-  char *profile_dir = (char *) mymalloc (strlen (homedir) + 1 + strlen (DOT_HASHCAT) + 1);
+  size_t len = strlen (homedir) + 1 + strlen (DOT_HASHCAT) + 1;
+
+  char *profile_dir = (char *) mymalloc (len + 1);
 
-  sprintf (profile_dir, "%s/%s", homedir, DOT_HASHCAT);
+  snprintf (profile_dir, len, "%s/%s", homedir, DOT_HASHCAT);
 
   return profile_dir;
 }
@@ -4155,13 +4178,44 @@ char *get_session_dir (const char *profile_dir)
 {
   #define SESSIONS_FOLDER "sessions"
 
-  char *session_dir = (char *) mymalloc (strlen (profile_dir) + 1 + strlen (SESSIONS_FOLDER) + 1);
+  size_t len = strlen (profile_dir) + 1 + strlen (SESSIONS_FOLDER) + 1;
+
+  char *session_dir = (char *) mymalloc (len + 1);
 
-  sprintf (session_dir, "%s/%s", profile_dir, SESSIONS_FOLDER);
+  snprintf (session_dir, len, "%s/%s", profile_dir, SESSIONS_FOLDER);
 
   return session_dir;
 }
 
+uint count_lines (FILE *fd)
+{
+  uint cnt = 0;
+
+  char *buf = (char *) mymalloc (BUFSIZ + 1);
+
+  char prev = '\n';
+
+  while (!feof (fd))
+  {
+    size_t nread = fread (buf, sizeof (char), BUFSIZ, fd);
+
+    if (nread < 1) continue;
+
+    size_t i;
+
+    for (i = 0; i < nread; i++)
+    {
+      if (prev == '\n') cnt++;
+
+      prev = buf[i];
+    }
+  }
+
+  myfree (buf);
+
+  return cnt;
+}
+
 void truecrypt_crc32 (const char *filename, u8 keytab[64])
 {
   uint crc = ~0;
@@ -4200,15 +4254,36 @@ void truecrypt_crc32 (const char *filename, u8 keytab[64])
   myfree (buf);
 }
 
+#ifdef OSX
+int pthread_setaffinity_np (pthread_t thread, size_t cpu_size, cpu_set_t *cpu_set)
+{
+  int core;
+
+  for (core = 0; core < (8 * (int)cpu_size); core++)
+    if (CPU_ISSET(core, cpu_set)) break;
+
+  thread_affinity_policy_data_t policy = { core };
+
+  const int rc = thread_policy_set (pthread_mach_thread_np (thread), THREAD_AFFINITY_POLICY, (thread_policy_t) &policy, 1);
+
+  if (data.quiet == 0)
+  {
+    if (rc != KERN_SUCCESS)
+    {
+      log_error ("ERROR: %s : %d", "thread_policy_set()", rc);
+    }
+  }
+
+  return rc;
+}
+#endif
+
 void set_cpu_affinity (char *cpu_affinity)
 {
   #ifdef WIN
   DWORD_PTR aff_mask = 0;
-  #endif
-
-  #ifdef LINUX
+  #elif _POSIX
   cpu_set_t cpuset;
-
   CPU_ZERO (&cpuset);
   #endif
 
@@ -4226,9 +4301,7 @@ void set_cpu_affinity (char *cpu_affinity)
       {
         #ifdef WIN
         aff_mask = 0;
-        #endif
-
-        #ifdef LINUX
+        #elif _POSIX
         CPU_ZERO (&cpuset);
         #endif
 
@@ -4244,9 +4317,7 @@ void set_cpu_affinity (char *cpu_affinity)
 
       #ifdef WIN
       aff_mask |= 1 << (cpu_id - 1);
-      #endif
-
-      #ifdef LINUX
+      #elif _POSIX
       CPU_SET ((cpu_id - 1), &cpuset);
       #endif
 
@@ -4258,9 +4329,7 @@ void set_cpu_affinity (char *cpu_affinity)
   #ifdef WIN
   SetProcessAffinityMask (GetCurrentProcess (), aff_mask);
   SetThreadAffinityMask (GetCurrentThread (), aff_mask);
-  #endif
-
-  #ifdef LINUX
+  #elif _POSIX
   pthread_t thread = pthread_self ();
   pthread_setaffinity_np (thread, sizeof (cpu_set_t), &cpuset);
   #endif
@@ -4294,7 +4363,7 @@ int sort_by_salt (const void *v1, const void *v2)
 
   uint n;
 
-  n = 12;
+  n = 16;
 
   while (n--)
   {
@@ -4324,7 +4393,7 @@ int sort_by_salt_buf (const void *v1, const void *v2)
   const salt_t *s1 = h1->salt;
   const salt_t *s2 = h2->salt;
 
-  uint n = 12;
+  uint n = 16;
 
   while (n--)
   {
@@ -4344,7 +4413,7 @@ int sort_by_hash_t_salt (const void *v1, const void *v2)
   const salt_t *s2 = h2->salt;
 
   // testphase: this should work
-  uint n = 12;
+  uint n = 16;
 
   while (n--)
   {
@@ -4377,8 +4446,8 @@ int sort_by_hash_t_salt_hccap (const void *v1, const void *v2)
   const salt_t *s1 = h1->salt;
   const salt_t *s2 = h2->salt;
 
-  // 12 - 2 (since last 2 uints contain the digest)
-  uint n = 10;
+  // 16 - 2 (since last 2 uints contain the digest)
+  uint n = 14;
 
   while (n--)
   {
@@ -4472,7 +4541,7 @@ int sort_by_dictstat (const void *s1, const void *s2)
   dictstat_t *d1 = (dictstat_t *) s1;
   dictstat_t *d2 = (dictstat_t *) s2;
 
-  #ifdef _POSIX
+  #ifdef LINUX
   d2->stat.st_atim = d1->stat.st_atim;
   #else
   d2->stat.st_atime = d1->stat.st_atime;
@@ -4687,6 +4756,40 @@ int sort_by_digest_p0p1 (const void *v1, const void *v2)
   return (0);
 }
 
+int sort_by_tuning_db_alias (const void *v1, const void *v2)
+{
+  const tuning_db_alias_t *t1 = (const tuning_db_alias_t *) v1;
+  const tuning_db_alias_t *t2 = (const tuning_db_alias_t *) v2;
+
+  const int res1 = strcmp (t1->device_name, t2->device_name);
+
+  if (res1 != 0) return (res1);
+
+  return 0;
+}
+
+int sort_by_tuning_db_entry (const void *v1, const void *v2)
+{
+  const tuning_db_entry_t *t1 = (const tuning_db_entry_t *) v1;
+  const tuning_db_entry_t *t2 = (const tuning_db_entry_t *) v2;
+
+  const int res1 = strcmp (t1->device_name, t2->device_name);
+
+  if (res1 != 0) return (res1);
+
+  const int res2 = t1->attack_mode
+                 - t2->attack_mode;
+
+  if (res2 != 0) return (res2);
+
+  const int res3 = t1->hash_type
+                 - t2->hash_type;
+
+  if (res3 != 0) return (res3);
+
+  return 0;
+}
+
 void format_debug (char *debug_file, uint debug_mode, unsigned char *orig_plain_ptr, uint orig_plain_len, unsigned char *mod_plain_ptr, uint mod_plain_len, char *rule_buf, int rule_len)
 {
   uint outfile_autohex = data.outfile_autohex;
@@ -4698,6 +4801,8 @@ void format_debug (char *debug_file, uint debug_mode, unsigned char *orig_plain_
   if (debug_file != NULL)
   {
     debug_fp = fopen (debug_file, "ab");
+
+    lock_file (debug_fp);
   }
   else
   {
@@ -4835,7 +4940,7 @@ void format_output (FILE *out_fp, char *out_buf, unsigned char *plain_ptr, const
 
     #ifdef _POSIX
     #ifdef __x86_64__
-    fprintf (out_fp, "%lu", crackpos);
+    fprintf (out_fp, "%lu", (unsigned long) crackpos);
     #else
     fprintf (out_fp, "%llu", crackpos);
     #endif
@@ -5073,9 +5178,7 @@ void handle_left_request_lm (pot_t *pot, uint pot_cnt, char *input_buf, int inpu
 
   uint user_len = input_len - 32;
 
-  char hash_output[user_len + 33];
-
-  memset (hash_output, 0, sizeof (hash_output));
+  char *hash_output = (char *) mymalloc (33);
 
   memcpy (hash_output, input_buf, input_len);
 
@@ -5099,6 +5202,8 @@ void handle_left_request_lm (pot_t *pot, uint pot_cnt, char *input_buf, int inpu
 
   format_output (out_fp, hash_output, NULL, 0, 0, NULL, 0);
 
+  myfree (hash_output);
+
   if (weak_hash_found == 1) myfree (pot_right_ptr);
 }
 
@@ -5405,14 +5510,31 @@ char **scan_directory (const char *path)
 
   int num_files = 0;
 
-  DIR *d;
+  DIR *d = NULL;
 
   if ((d = opendir (tmp_path)) != NULL)
   {
+    #ifdef OSX
+    struct dirent e;
+
+    for (;;) {
+      memset (&e, 0, sizeof (e));
+      struct dirent *de = NULL;
+
+      if (readdir_r (d, &e, &de) != 0)
+      {
+        log_error ("ERROR: readdir_r() failed");
+
+        break;
+      }
+
+      if (de == NULL) break;
+    #else
     struct dirent *de;
 
     while ((de = readdir (d)) != NULL)
     {
+    #endif
       if ((strcmp (de->d_name, ".") == 0) || (strcmp (de->d_name, "..") == 0)) continue;
 
       int path_size = strlen (tmp_path) + 1 + strlen (de->d_name);
@@ -5495,6 +5617,10 @@ char *stroptitype (const uint opti_type)
     case OPTI_TYPE_SINGLE_SALT:       return ((char *) OPTI_STR_SINGLE_SALT);       break;
     case OPTI_TYPE_BRUTE_FORCE:       return ((char *) OPTI_STR_BRUTE_FORCE);       break;
     case OPTI_TYPE_RAW_HASH:          return ((char *) OPTI_STR_RAW_HASH);          break;
+    case OPTI_TYPE_USES_BITS_8:       return ((char *) OPTI_STR_USES_BITS_8);       break;
+    case OPTI_TYPE_USES_BITS_16:      return ((char *) OPTI_STR_USES_BITS_16);      break;
+    case OPTI_TYPE_USES_BITS_32:      return ((char *) OPTI_STR_USES_BITS_32);      break;
+    case OPTI_TYPE_USES_BITS_64:      return ((char *) OPTI_STR_USES_BITS_64);      break;
   }
 
   return (NULL);
@@ -5708,6 +5834,7 @@ char *strhashtype (const uint hash_mode)
     case 12800: return ((char *) HT_12800); break;
     case 12900: return ((char *) HT_12900); break;
     case 13000: return ((char *) HT_13000); break;
+    case 13100: return ((char *) HT_13100); break;
   }
 
   return ((char *) "Unknown");
@@ -5727,6 +5854,7 @@ char *strstatus (const uint devices_status)
     case  STATUS_QUIT:               return ((char *) ST_0007); break;
     case  STATUS_BYPASS:             return ((char *) ST_0008); break;
     case  STATUS_STOP_AT_CHECKPOINT: return ((char *) ST_0009); break;
+    case  STATUS_AUTOTUNE:           return ((char *) ST_0010); break;
   }
 
   return ((char *) "Unknown");
@@ -5745,7 +5873,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
 
   uint len = 4096;
 
-  uint digest_buf[64];
+  uint digest_buf[64] = { 0 };
 
   u64 *digest_buf64 = (u64 *) digest_buf;
 
@@ -5962,9 +6090,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
 
     if (opts_type & OPTS_TYPE_ST_HEX)
     {
-      char tmp[64];
-
-      memset (tmp, 0, sizeof (tmp));
+      char tmp[64] = { 0 };
 
       for (uint i = 0, j = 0; i < len; i += 1, j += 2)
       {
@@ -5987,24 +6113,17 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
   // some modes require special encoding
   //
 
-  uint out_buf_plain[256];
-  uint out_buf_salt[256];
-
-  char tmp_buf[1024];
+  uint out_buf_plain[256] = { 0 };
+  uint out_buf_salt[256] = { 0 };
 
-  memset (out_buf_plain, 0, sizeof (out_buf_plain));
-  memset (out_buf_salt,  0, sizeof (out_buf_salt));
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  char tmp_buf[1024] = { 0 };
 
   char *ptr_plain = (char *) out_buf_plain;
   char *ptr_salt  = (char *) out_buf_salt;
 
   if (hash_mode == 22)
   {
-    char username[30];
-
-    memset (username, 0, sizeof (username));
+    char username[30] = { 0 };
 
     memcpy (username, salt.salt_buf, salt.salt_len - 22);
 
@@ -6444,7 +6563,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
 
     wpa_t *wpa = &wpas[salt_pos];
 
-    uint pke[25];
+    uint pke[25] = { 0 };
 
     char *pke_ptr = (char *) pke;
 
@@ -6453,8 +6572,8 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
       pke[i] = byte_swap_32 (wpa->pke[i]);
     }
 
-    unsigned char mac1[6];
-    unsigned char mac2[6];
+    unsigned char mac1[6] = { 0 };
+    unsigned char mac2[6] = { 0 };
 
     memcpy (mac1, pke_ptr + 23, 6);
     memcpy (mac2, pke_ptr + 29, 6);
@@ -6663,15 +6782,10 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
 
     netntlm_t *netntlm = &netntlms[salt_pos];
 
-    char user_buf[64];
-    char domain_buf[64];
-    char srvchall_buf[1024];
-    char clichall_buf[1024];
-
-    memset (user_buf,     0, sizeof (user_buf));
-    memset (domain_buf,   0, sizeof (domain_buf));
-    memset (srvchall_buf, 0, sizeof (srvchall_buf));
-    memset (clichall_buf, 0, sizeof (clichall_buf));
+    char user_buf[64] = { 0 };
+    char domain_buf[64] = { 0 };
+    char srvchall_buf[1024] = { 0 };
+    char clichall_buf[1024] = { 0 };
 
     for (uint i = 0, j = 0; j < netntlm->user_len; i += 1, j += 2)
     {
@@ -6719,15 +6833,10 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
 
     netntlm_t *netntlm = &netntlms[salt_pos];
 
-    char user_buf[64];
-    char domain_buf[64];
-    char srvchall_buf[1024];
-    char clichall_buf[1024];
-
-    memset (user_buf,     0, sizeof (user_buf));
-    memset (domain_buf,   0, sizeof (domain_buf));
-    memset (srvchall_buf, 0, sizeof (srvchall_buf));
-    memset (clichall_buf, 0, sizeof (clichall_buf));
+    char user_buf[64] = { 0 };
+    char domain_buf[64] = { 0 };
+    char srvchall_buf[1024] = { 0 };
+    char clichall_buf[1024] = { 0 };
 
     for (uint i = 0, j = 0; j < netntlm->user_len; i += 1, j += 2)
     {
@@ -6871,7 +6980,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
 
     pbkdf2_sha512_t *pbkdf2_sha512  = &pbkdf2_sha512s[salt_pos];
 
-    uint esalt[16];
+    uint esalt[8] = { 0 };
 
     esalt[0] = byte_swap_32 (pbkdf2_sha512->salt_buf[0]);
     esalt[1] = byte_swap_32 (pbkdf2_sha512->salt_buf[1]);
@@ -6980,7 +7089,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
     u8 *ptr_timestamp = (u8 *) krb5pa->timestamp;
     u8 *ptr_checksum  = (u8 *) krb5pa->checksum;
 
-    char data[128];
+    char data[128] = { 0 };
 
     char *ptr_data = data;
 
@@ -7068,7 +7177,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
 
     cloudkey_t *cloudkey = &cloudkeys[salt_pos];
 
-    char data_buf[4096];
+    char data_buf[4096] = { 0 };
 
     for (int i = 0, j = 0; i < 512; i += 1, j += 8)
     {
@@ -7172,7 +7281,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
 
     androidfde_t *androidfde = &androidfdes[salt_pos];
 
-    char tmp[3073];
+    char tmp[3073] = { 0 };
 
     for (uint i = 0, j = 0; i < 384; i += 1, j += 8)
     {
@@ -7199,9 +7308,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
     uint r = salt.scrypt_r;
     uint p = salt.scrypt_p;
 
-    char base64_salt[32];
-
-    memset (base64_salt, 0, 32);
+    char base64_salt[32] = { 0 };
 
     base64_encode (int_to_base64, (const u8 *) salt.salt_buf, salt.salt_len, (u8 *) base64_salt);
 
@@ -7253,8 +7360,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
     digest_buf[7] = byte_swap_32 (digest_buf[7]);
     digest_buf[8] = 0; // needed for base64_encode ()
 
-    char tmp_buf[64];
-    memset (tmp_buf, 0, sizeof (tmp_buf));
+    char tmp_buf[64] = { 0 };
 
     base64_encode (int_to_itoa64, (const u8 *) digest_buf, 32, (u8 *) tmp_buf);
     tmp_buf[43] = 0; // cut it here
@@ -7275,8 +7381,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
     digest_buf[7] = byte_swap_32 (digest_buf[7]);
     digest_buf[8] = 0; // needed for base64_encode ()
 
-    char tmp_buf[64];
-    memset (tmp_buf, 0, sizeof (tmp_buf));
+    char tmp_buf[64] = { 0 };
 
     base64_encode (int_to_itoa64, (const u8 *) digest_buf, 32, (u8 *) tmp_buf);
     tmp_buf[43] = 0; // cut it here
@@ -7526,8 +7631,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
     digest_buf[7] = byte_swap_32 (digest_buf[7]);
     digest_buf[8] = 0; // needed for base64_encode ()
 
-    char tmp_buf[64];
-    memset (tmp_buf, 0, sizeof (tmp_buf));
+    char tmp_buf[64] = { 0 };
 
     base64_encode (int_to_base64, (const u8 *) digest_buf, 32, (u8 *) tmp_buf);
 
@@ -7555,15 +7659,13 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
 
     // challenge
 
-    char challenge[100];
-
-    memset (challenge, 0, sizeof (challenge));
+    char challenge[100] = { 0 };
 
     base64_encode (int_to_base64, (const u8 *) salt.salt_buf, salt.salt_len, (u8 *) challenge);
 
     // response
 
-    char tmp_buf[100];
+    char tmp_buf[100] = { 0 };
 
     uint tmp_len = snprintf (tmp_buf, 100, "%s %08x%08x%08x%08x",
       (char *) cram_md5->user,
@@ -7572,9 +7674,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
       digest_buf[2],
       digest_buf[3]);
 
-    char response[100];
-
-    memset (response, 0, sizeof (response));
+    char response[100] = { 0 };
 
     base64_encode (int_to_base64, (const u8 *) tmp_buf, tmp_len, (u8 *) response);
 
@@ -7582,9 +7682,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
   }
   else if (hash_mode == 10300)
   {
-    char tmp_buf[100];
-
-    memset (tmp_buf, 0, sizeof (tmp_buf));
+    char tmp_buf[100] = { 0 };
 
     memcpy (tmp_buf +  0, digest_buf, 20);
     memcpy (tmp_buf + 20, salt.salt_buf, salt.salt_len);
@@ -7593,9 +7691,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
 
     // base64 encode it
 
-    char base64_encoded[100];
-
-    memset (base64_encoded, 0, sizeof (base64_encoded));
+    char base64_encoded[100] = { 0 };
 
     base64_encode (int_to_base64, (const u8 *) tmp_buf, tmp_len, (u8 *) base64_encoded);
 
@@ -8046,7 +8142,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
   {
     // encode iteration count
 
-    char salt_iter[5];
+    char salt_iter[5] = { 0 };
 
     salt_iter[0] = int_to_itoa64 ((salt.salt_iter      ) & 0x3f);
     salt_iter[1] = int_to_itoa64 ((salt.salt_iter >>  6) & 0x3f);
@@ -8183,6 +8279,36 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
       byte_swap_32 (digest_buf[1])
     );
   }
+  else if (hash_mode == 13100)
+  {
+    krb5tgs_t *krb5tgss = (krb5tgs_t *) data.esalts_buf;
+
+    krb5tgs_t *krb5tgs = &krb5tgss[salt_pos];
+
+    u8 *ptr_checksum  = (u8 *) krb5tgs->checksum;
+    u8 *ptr_edata2 = (u8 *) krb5tgs->edata2;
+
+    char data[256] = { 0 };
+
+    char *ptr_data = data;
+
+    for (uint i = 0; i < 16; i++, ptr_data += 2)
+      sprintf (ptr_data, "%02x", ptr_checksum[i]);
+
+    /* skip '$' */
+    ptr_data++;
+
+    for (uint i = 0; i < 32; i++, ptr_data += 2)
+      sprintf (ptr_data, "%02x", ptr_edata2[i]);
+
+    *ptr_data = 0;
+
+    snprintf (out_buf, len-1, "%s$%s$%s$%s",
+      SIGNATURE_KRB5TGS,
+      (char *) krb5tgs->account_info,
+      data,
+      data + 33);
+  }
   else
   {
     if (hash_type == HASH_TYPE_MD4)
@@ -8382,7 +8508,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
       digest_buf[ 2] = byte_swap_32 (digest_buf[ 2]);
       digest_buf[ 3] = byte_swap_32 (digest_buf[ 3]);
 
-      char buf[16];
+      char buf[16] = { 0 };
 
       memcpy (buf + 0, salt.salt_buf, 5);
       memcpy (buf + 5, digest_buf, 9);
@@ -8398,9 +8524,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
     }
     else if (hash_type == HASH_TYPE_LOTUS8)
     {
-      char buf[52];
-
-      memset (buf, 0, sizeof (buf));
+      char buf[52] = { 0 };
 
       // salt
 
@@ -8464,7 +8588,7 @@ void to_hccap_t (hccap_t *hccap, uint salt_pos, uint digest_pos)
 
   if (wpa->keyver != 1)
   {
-    uint eapol_tmp[64];
+    uint eapol_tmp[64] = { 0 };
 
     for (uint i = 0; i < 64; i++)
     {
@@ -8478,7 +8602,7 @@ void to_hccap_t (hccap_t *hccap, uint salt_pos, uint digest_pos)
     memcpy (hccap->eapol, wpa->eapol, wpa->eapol_size);
   }
 
-  uint pke_tmp[25];
+  uint pke_tmp[25] = { 0 };
 
   for (int i = 5; i < 25; i++)
   {
@@ -8500,7 +8624,7 @@ void to_hccap_t (hccap_t *hccap, uint salt_pos, uint digest_pos)
 
   if (wpa->keyver != 1)
   {
-    uint digest_tmp[4];
+    uint digest_tmp[4] = { 0 };
 
     digest_tmp[0] = byte_swap_32 (digest_ptr[0]);
     digest_tmp[1] = byte_swap_32 (digest_ptr[1]);
@@ -8610,9 +8734,9 @@ void myquit ()
 
 void load_kernel (const char *kernel_file, int num_devices, size_t *kernel_lengths, const u8 **kernel_sources)
 {
-  FILE *fp;
+  FILE *fp = fopen (kernel_file, "rb");
 
-  if ((fp = fopen (kernel_file, "rb")) != NULL)
+  if (fp != NULL)
   {
     struct stat st;
 
@@ -8654,12 +8778,16 @@ void load_kernel (const char *kernel_file, int num_devices, size_t *kernel_lengt
 
 void writeProgramBin (char *dst, u8 *binary, size_t binary_size)
 {
-  FILE *fp = fopen (dst, "wb");
+  if (binary_size > 0)
+  {
+    FILE *fp = fopen (dst, "wb");
 
-  fwrite (binary, sizeof (u8), binary_size, fp);
+    lock_file (fp);
+    fwrite (binary, sizeof (u8), binary_size, fp);
 
-  fflush (fp);
-  fclose (fp);
+    fflush (fp);
+    fclose (fp);
+  }
 }
 
 /**
@@ -8689,13 +8817,11 @@ restore_data_t *init_restore (int argc, char **argv)
 
       if (rd->pid)
       {
-        char pidbin[BUFSIZ];
+        char pidbin[BUFSIZ] = { 0 };
 
-        int pidbin_len;
+        int pidbin_len = -1;
 
         #ifdef _POSIX
-        memset (pidbin, 0, sizeof (pidbin));
-
         snprintf (pidbin, sizeof (pidbin) - 1, "/proc/%d/cmdline", rd->pid);
 
         FILE *fd = fopen (pidbin, "rb");
@@ -8727,11 +8853,9 @@ restore_data_t *init_restore (int argc, char **argv)
         #elif _WIN
         HANDLE hProcess = OpenProcess (PROCESS_ALL_ACCESS, FALSE, rd->pid);
 
-        char pidbin2[BUFSIZ];
-
-        int pidbin2_len;
+        char pidbin2[BUFSIZ] = { 0 };
 
-        memset (pidbin2, 0, sizeof (pidbin2));
+        int pidbin2_len = -1;
 
         pidbin_len = GetModuleFileName (NULL, pidbin, BUFSIZ);
         pidbin2_len = GetModuleFileNameEx (hProcess, NULL, pidbin2, BUFSIZ);
@@ -8805,7 +8929,7 @@ void read_restore (const char *eff_restore_file, restore_data_t *rd)
 
   for (uint i = 0; i < rd->argc; i++)
   {
-    char buf[BUFSIZ];
+    char buf[BUFSIZ] = { 0 };
 
     if (fgets (buf, BUFSIZ - 1, fp) == NULL)
     {
@@ -8823,7 +8947,7 @@ void read_restore (const char *eff_restore_file, restore_data_t *rd)
 
   fclose (fp);
 
-  char new_cwd[256];
+  char new_cwd[1024] = { 0 };
 
   char *nwd = getcwd (new_cwd, sizeof (new_cwd));
 
@@ -8844,7 +8968,6 @@ void read_restore (const char *eff_restore_file, restore_data_t *rd)
     log_info ("WARNING: Found old restore file, updating path to %s...", new_cwd);
   }
 
-
   if (chdir (rd->cwd))
   {
     log_error ("ERROR: cannot chdir to %s: %s", rd->cwd, strerror (errno));
@@ -8916,421 +9039,322 @@ void write_restore (const char *new_restore_file, restore_data_t *rd)
   fclose (fp);
 }
 
-void cycle_restore ()
-{
-  const char *eff_restore_file = data.eff_restore_file;
-  const char *new_restore_file = data.new_restore_file;
+void cycle_restore ()
+{
+  const char *eff_restore_file = data.eff_restore_file;
+  const char *new_restore_file = data.new_restore_file;
+
+  restore_data_t *rd = data.rd;
+
+  write_restore (new_restore_file, rd);
+
+  struct stat st;
+
+  memset (&st, 0, sizeof(st));
+
+  if (stat (eff_restore_file, &st) == 0)
+  {
+    if (unlink (eff_restore_file))
+    {
+      log_info ("WARN: unlink file '%s': %s", eff_restore_file, strerror (errno));
+    }
+  }
+
+  if (rename (new_restore_file, eff_restore_file))
+  {
+    log_info ("WARN: rename file '%s' to '%s': %s", new_restore_file, eff_restore_file, strerror (errno));
+  }
+}
+
+void check_checkpoint ()
+{
+  // if (data.restore_disable == 1) break;  (this is already implied by previous checks)
+
+  u64 words_cur = get_lowest_words_done ();
+
+  if (words_cur != data.checkpoint_cur_words)
+  {
+    myabort ();
+  }
+}
+
+/**
+ * tuning db
+ */
+
+void tuning_db_destroy (tuning_db_t *tuning_db)
+{
+  int i;
+
+  for (i = 0; i < tuning_db->alias_cnt; i++)
+  {
+    tuning_db_alias_t *alias = &tuning_db->alias_buf[i];
+
+    myfree (alias->device_name);
+    myfree (alias->alias_name);
+  }
+
+  for (i = 0; i < tuning_db->entry_cnt; i++)
+  {
+    tuning_db_entry_t *entry = &tuning_db->entry_buf[i];
+
+    myfree (entry->device_name);
+  }
+
+  myfree (tuning_db->alias_buf);
+  myfree (tuning_db->entry_buf);
+
+  myfree (tuning_db);
+}
+
+tuning_db_t *tuning_db_alloc (FILE *fp)
+{
+  tuning_db_t *tuning_db = (tuning_db_t *) mymalloc (sizeof (tuning_db_t));
+
+  int num_lines = count_lines (fp);
+
+  // a bit over-allocated
+
+  tuning_db->alias_buf = (tuning_db_alias_t *) mycalloc (num_lines + 1, sizeof (tuning_db_alias_t));
+  tuning_db->alias_cnt = 0;
+
+  tuning_db->entry_buf = (tuning_db_entry_t *) mycalloc (num_lines + 1, sizeof (tuning_db_entry_t));
+  tuning_db->entry_cnt = 0;
+
+  return tuning_db;
+}
+
+tuning_db_t *tuning_db_init (const char *tuning_db_file)
+{
+  FILE *fp = fopen (tuning_db_file, "rb");
+
+  if (fp == NULL)
+  {
+    log_error ("%s: %s", tuning_db_file, strerror (errno));
+
+    exit (-1);
+  }
+
+  tuning_db_t *tuning_db = tuning_db_alloc (fp);
+
+  rewind (fp);
+
+  int line_num = 0;
+
+  while (!feof (fp))
+  {
+    char buf[BUFSIZ];
+
+    char *line_buf = fgets (buf, sizeof (buf) - 1, fp);
+
+    if (line_buf == NULL) break;
+
+    line_num++;
+
+    const int line_len = in_superchop (line_buf);
+
+    if (line_len == 0) continue;
+
+    if (line_buf[0] == '#') continue;
+
+    // start processing
+
+    char *token_ptr[7] = { NULL };
+
+    int token_cnt = 0;
+
+    char *next = strtok (line_buf, "\t ");
+
+    token_ptr[token_cnt] = next;
+
+    token_cnt++;
+
+    while ((next = strtok (NULL, "\t ")) != NULL)
+    {
+      token_ptr[token_cnt] = next;
+
+      token_cnt++;
+    }
+
+    if (token_cnt == 2)
+    {
+      char *device_name = token_ptr[0];
+      char *alias_name  = token_ptr[1];
+
+      tuning_db_alias_t *alias = &tuning_db->alias_buf[tuning_db->alias_cnt];
+
+      alias->device_name = mystrdup (device_name);
+      alias->alias_name  = mystrdup (alias_name);
+
+      tuning_db->alias_cnt++;
+    }
+    else if (token_cnt == 6)
+    {
+      if ((token_ptr[1][0] != '0') &&
+          (token_ptr[1][0] != '1') &&
+          (token_ptr[1][0] != '3') &&
+          (token_ptr[1][0] != '*'))
+      {
+        log_info ("WARNING: Tuning-db: Invalid attack_mode '%c' in Line '%u'", token_ptr[1][0], line_num);
+
+        continue;
+      }
+
+      if ((token_ptr[3][0] != '1') &&
+          (token_ptr[3][0] != '2') &&
+          (token_ptr[3][0] != '4') &&
+          (token_ptr[3][0] != '8') &&
+          (token_ptr[3][0] != 'N'))
+      {
+        log_info ("WARNING: Tuning-db: Invalid vector_width '%c' in Line '%u'", token_ptr[3][0], line_num);
+
+        continue;
+      }
+
+      char *device_name = token_ptr[0];
+
+      int attack_mode      = -1;
+      int hash_type        = -1;
+      int vector_width     = -1;
+      int kernel_accel     = -1;
+      int kernel_loops     = -1;
+
+      if (token_ptr[1][0] != '*') attack_mode      = atoi (token_ptr[1]);
+      if (token_ptr[2][0] != '*') hash_type        = atoi (token_ptr[2]);
+      if (token_ptr[3][0] != 'N') vector_width     = atoi (token_ptr[3]);
+
+      if (token_ptr[4][0] != 'A')
+      {
+        kernel_accel = atoi (token_ptr[4]);
+
+        if ((kernel_accel < 1) || (kernel_accel > 1024))
+        {
+          log_info ("WARNING: Tuning-db: Invalid kernel_accel '%d' in Line '%u'", kernel_accel, line_num);
+
+          continue;
+        }
+      }
+      else
+      {
+        kernel_accel = 0;
+      }
+
+      if (token_ptr[5][0] != 'A')
+      {
+        kernel_loops = atoi (token_ptr[5]);
+
+        if ((kernel_loops < 1) || (kernel_loops > 1024))
+        {
+          log_info ("WARNING: Tuning-db: Invalid kernel_loops '%d' in Line '%u'", kernel_loops, line_num);
+
+          continue;
+        }
+      }
+      else
+      {
+        kernel_loops = 0;
+      }
+
+      tuning_db_entry_t *entry = &tuning_db->entry_buf[tuning_db->entry_cnt];
+
+      entry->device_name  = mystrdup (device_name);
+      entry->attack_mode  = attack_mode;
+      entry->hash_type    = hash_type;
+      entry->vector_width = vector_width;
+      entry->kernel_accel = kernel_accel;
+      entry->kernel_loops = kernel_loops;
+
+      tuning_db->entry_cnt++;
+    }
+    else
+    {
+      log_info ("WARNING: Tuning-db: Invalid number of token in Line '%u'", line_num);
+
+      continue;
+    }
+  }
+
+  fclose (fp);
+
+  // todo: print loaded 'cnt' message
+
+  // sort the database
+
+  qsort (tuning_db->alias_buf, tuning_db->alias_cnt, sizeof (tuning_db_alias_t), sort_by_tuning_db_alias);
+  qsort (tuning_db->entry_buf, tuning_db->entry_cnt, sizeof (tuning_db_entry_t), sort_by_tuning_db_entry);
+
+  return tuning_db;
+}
+
+tuning_db_entry_t *tuning_db_search (tuning_db_t *tuning_db, char *device_name, int attack_mode, int hash_type)
+{
+  static tuning_db_entry_t s;
+
+  // first we need to convert all spaces in the device_name to underscore
+
+  char *device_name_nospace = strdup (device_name);
+
+  int device_name_length = strlen (device_name_nospace);
+
+  int i;
+
+  for (i = 0; i < device_name_length; i++)
+  {
+    if (device_name_nospace[i] == ' ') device_name_nospace[i] = '_';
+  }
+
+  // find out if there's an alias configured
+
+  tuning_db_alias_t a;
+
+  a.device_name = device_name_nospace;
+
+  tuning_db_alias_t *alias = bsearch (&a, tuning_db->alias_buf, tuning_db->alias_cnt, sizeof (tuning_db_alias_t), sort_by_tuning_db_alias);
+
+  char *alias_name = (alias == NULL) ? NULL : alias->alias_name;
+
+  // attack-mode 6 and 7 are attack-mode 1 basically
+
+  if (attack_mode == 6) attack_mode = 1;
+  if (attack_mode == 7) attack_mode = 1;
 
-  restore_data_t *rd = data.rd;
+  // bsearch is not ideal but fast enough
 
-  write_restore (new_restore_file, rd);
+  s.device_name = device_name_nospace;
+  s.attack_mode = attack_mode;
+  s.hash_type   = hash_type;
 
-  struct stat st;
+  tuning_db_entry_t *entry = NULL;
 
-  memset (&st, 0, sizeof(st));
+  // this will produce all 2^3 combinations required
 
-  if (stat (eff_restore_file, &st) == 0)
+  for (i = 0; i < 8; i++)
   {
-    if (unlink (eff_restore_file))
-    {
-      log_info ("WARN: unlink file '%s': %s", eff_restore_file, strerror (errno));
-    }
-  }
+    s.device_name = (i & 1) ? "*" : device_name_nospace;
+    s.attack_mode = (i & 2) ?  -1 : attack_mode;
+    s.hash_type   = (i & 4) ?  -1 : hash_type;
 
-  if (rename (new_restore_file, eff_restore_file))
-  {
-    log_info ("WARN: rename file '%s' to '%s': %s", new_restore_file, eff_restore_file, strerror (errno));
-  }
-}
+    entry = bsearch (&s, tuning_db->entry_buf, tuning_db->entry_cnt, sizeof (tuning_db_entry_t), sort_by_tuning_db_entry);
 
-void check_checkpoint ()
-{
-  // if (data.restore_disable == 1) break;  (this is already implied by previous checks)
+    if (entry != NULL) break;
 
-  u64 words_cur = get_lowest_words_done ();
+    // in non-wildcard mode also check the alias_name
 
-  if (words_cur != data.checkpoint_cur_words)
-  {
-    myabort ();
-  }
-}
+    if (((i & 1) == 0) && (alias_name != NULL))
+    {
+      s.device_name = alias_name;
 
-/**
- * adjustments
- */
+      entry = bsearch (&s, tuning_db->entry_buf, tuning_db->entry_cnt, sizeof (tuning_db_entry_t), sort_by_tuning_db_entry);
 
-uint set_kernel_accel (uint hash_mode)
-{
-  switch (hash_mode)
-  {
-    case     0: return GET_ACCEL (0);
-    case    10: return GET_ACCEL (10);
-    case    11: return GET_ACCEL (11);
-    case    12: return GET_ACCEL (12);
-    case    20: return GET_ACCEL (20);
-    case    21: return GET_ACCEL (21);
-    case    22: return GET_ACCEL (22);
-    case    23: return GET_ACCEL (23);
-    case    30: return GET_ACCEL (30);
-    case    40: return GET_ACCEL (40);
-    case    50: return GET_ACCEL (50);
-    case    60: return GET_ACCEL (60);
-    case   100: return GET_ACCEL (100);
-    case   101: return GET_ACCEL (101);
-    case   110: return GET_ACCEL (110);
-    case   111: return GET_ACCEL (111);
-    case   112: return GET_ACCEL (112);
-    case   120: return GET_ACCEL (120);
-    case   121: return GET_ACCEL (121);
-    case   122: return GET_ACCEL (122);
-    case   124: return GET_ACCEL (124);
-    case   130: return GET_ACCEL (130);
-    case   131: return GET_ACCEL (131);
-    case   132: return GET_ACCEL (132);
-    case   133: return GET_ACCEL (133);
-    case   140: return GET_ACCEL (140);
-    case   141: return GET_ACCEL (141);
-    case   150: return GET_ACCEL (150);
-    case   160: return GET_ACCEL (160);
-    case   190: return GET_ACCEL (190);
-    case   200: return GET_ACCEL (200);
-    case   300: return GET_ACCEL (300);
-    case   400: return GET_ACCEL (400);
-    case   500: return GET_ACCEL (500);
-    case   501: return GET_ACCEL (501);
-    case   900: return GET_ACCEL (900);
-    case   910: return GET_ACCEL (910);
-    case  1000: return GET_ACCEL (1000);
-    case  1100: return GET_ACCEL (1100);
-    case  1400: return GET_ACCEL (1400);
-    case  1410: return GET_ACCEL (1410);
-    case  1420: return GET_ACCEL (1420);
-    case  1421: return GET_ACCEL (1421);
-    case  1430: return GET_ACCEL (1430);
-    case  1440: return GET_ACCEL (1440);
-    case  1441: return GET_ACCEL (1441);
-    case  1450: return GET_ACCEL (1450);
-    case  1460: return GET_ACCEL (1460);
-    case  1500: return GET_ACCEL (1500);
-    case  1600: return GET_ACCEL (1600);
-    case  1700: return GET_ACCEL (1700);
-    case  1710: return GET_ACCEL (1710);
-    case  1711: return GET_ACCEL (1711);
-    case  1720: return GET_ACCEL (1720);
-    case  1722: return GET_ACCEL (1722);
-    case  1730: return GET_ACCEL (1730);
-    case  1731: return GET_ACCEL (1731);
-    case  1740: return GET_ACCEL (1740);
-    case  1750: return GET_ACCEL (1750);
-    case  1760: return GET_ACCEL (1760);
-    case  1800: return GET_ACCEL (1800);
-    case  2100: return GET_ACCEL (2100);
-    case  2400: return GET_ACCEL (2400);
-    case  2410: return GET_ACCEL (2410);
-    case  2500: return GET_ACCEL (2500);
-    case  2600: return GET_ACCEL (2600);
-    case  2611: return GET_ACCEL (2611);
-    case  2612: return GET_ACCEL (2612);
-    case  2711: return GET_ACCEL (2711);
-    case  2811: return GET_ACCEL (2811);
-    case  3000: return GET_ACCEL (3000);
-    case  3100: return GET_ACCEL (3100);
-    case  3200: return GET_ACCEL (3200);
-    case  3710: return GET_ACCEL (3710);
-    case  3711: return GET_ACCEL (3711);
-    case  3800: return GET_ACCEL (3800);
-    case  4300: return GET_ACCEL (4300);
-    case  4400: return GET_ACCEL (4400);
-    case  4500: return GET_ACCEL (4500);
-    case  4700: return GET_ACCEL (4700);
-    case  4800: return GET_ACCEL (4800);
-    case  4900: return GET_ACCEL (4900);
-    case  5000: return GET_ACCEL (5000);
-    case  5100: return GET_ACCEL (5100);
-    case  5200: return GET_ACCEL (5200);
-    case  5300: return GET_ACCEL (5300);
-    case  5400: return GET_ACCEL (5400);
-    case  5500: return GET_ACCEL (5500);
-    case  5600: return GET_ACCEL (5600);
-    case  5700: return GET_ACCEL (5700);
-    case  5800: return GET_ACCEL (5800);
-    case  6000: return GET_ACCEL (6000);
-    case  6100: return GET_ACCEL (6100);
-    case  6211: return GET_ACCEL (6211);
-    case  6212: return GET_ACCEL (6212);
-    case  6213: return GET_ACCEL (6213);
-    case  6221: return GET_ACCEL (6221);
-    case  6222: return GET_ACCEL (6222);
-    case  6223: return GET_ACCEL (6223);
-    case  6231: return GET_ACCEL (6231);
-    case  6232: return GET_ACCEL (6232);
-    case  6233: return GET_ACCEL (6233);
-    case  6241: return GET_ACCEL (6241);
-    case  6242: return GET_ACCEL (6242);
-    case  6243: return GET_ACCEL (6243);
-    case  6300: return GET_ACCEL (6300);
-    case  6400: return GET_ACCEL (6400);
-    case  6500: return GET_ACCEL (6500);
-    case  6600: return GET_ACCEL (6600);
-    case  6700: return GET_ACCEL (6700);
-    case  6800: return GET_ACCEL (6800);
-    case  6900: return GET_ACCEL (6900);
-    case  7100: return GET_ACCEL (7100);
-    case  7200: return GET_ACCEL (7200);
-    case  7300: return GET_ACCEL (7300);
-    case  7400: return GET_ACCEL (7400);
-    case  7500: return GET_ACCEL (7500);
-    case  7600: return GET_ACCEL (7600);
-    case  7700: return GET_ACCEL (7700);
-    case  7800: return GET_ACCEL (7800);
-    case  7900: return GET_ACCEL (7900);
-    case  8000: return GET_ACCEL (8000);
-    case  8100: return GET_ACCEL (8100);
-    case  8200: return GET_ACCEL (8200);
-    case  8300: return GET_ACCEL (8300);
-    case  8400: return GET_ACCEL (8400);
-    case  8500: return GET_ACCEL (8500);
-    case  8600: return GET_ACCEL (8600);
-    case  8700: return GET_ACCEL (8700);
-    case  8800: return GET_ACCEL (8800);
-    case  8900: return GET_ACCEL (8900);
-    case  9000: return GET_ACCEL (9000);
-    case  9100: return GET_ACCEL (9100);
-    case  9200: return GET_ACCEL (9200);
-    case  9300: return GET_ACCEL (9300);
-    case  9400: return GET_ACCEL (9400);
-    case  9500: return GET_ACCEL (9500);
-    case  9600: return GET_ACCEL (9600);
-    case  9700: return GET_ACCEL (9700);
-    case  9710: return GET_ACCEL (9710);
-    case  9720: return GET_ACCEL (9720);
-    case  9800: return GET_ACCEL (9800);
-    case  9810: return GET_ACCEL (9810);
-    case  9820: return GET_ACCEL (9820);
-    case  9900: return GET_ACCEL (9900);
-    case 10000: return GET_ACCEL (10000);
-    case 10100: return GET_ACCEL (10100);
-    case 10200: return GET_ACCEL (10200);
-    case 10300: return GET_ACCEL (10300);
-    case 10400: return GET_ACCEL (10400);
-    case 10410: return GET_ACCEL (10410);
-    case 10420: return GET_ACCEL (10420);
-    case 10500: return GET_ACCEL (10500);
-    case 10600: return GET_ACCEL (10600);
-    case 10700: return GET_ACCEL (10700);
-    case 10800: return GET_ACCEL (10800);
-    case 10900: return GET_ACCEL (10900);
-    case 11000: return GET_ACCEL (11000);
-    case 11100: return GET_ACCEL (11100);
-    case 11200: return GET_ACCEL (11200);
-    case 11300: return GET_ACCEL (11300);
-    case 11400: return GET_ACCEL (11400);
-    case 11500: return GET_ACCEL (11500);
-    case 11600: return GET_ACCEL (11600);
-    case 11700: return GET_ACCEL (11700);
-    case 11800: return GET_ACCEL (11800);
-    case 11900: return GET_ACCEL (11900);
-    case 12000: return GET_ACCEL (12000);
-    case 12100: return GET_ACCEL (12100);
-    case 12200: return GET_ACCEL (12200);
-    case 12300: return GET_ACCEL (12300);
-    case 12400: return GET_ACCEL (12400);
-    case 12500: return GET_ACCEL (12500);
-    case 12600: return GET_ACCEL (12600);
-    case 12700: return GET_ACCEL (12700);
-    case 12800: return GET_ACCEL (12800);
-    case 12900: return GET_ACCEL (12900);
-    case 13000: return GET_ACCEL (13000);
+      if (entry != NULL) break;
+    }
   }
 
-  return 0;
-}
+  // free converted device_name
 
-uint set_kernel_loops (uint hash_mode)
-{
-  switch (hash_mode)
-  {
-    case     0: return GET_LOOPS (0);
-    case    10: return GET_LOOPS (10);
-    case    11: return GET_LOOPS (11);
-    case    12: return GET_LOOPS (12);
-    case    20: return GET_LOOPS (20);
-    case    21: return GET_LOOPS (21);
-    case    22: return GET_LOOPS (22);
-    case    23: return GET_LOOPS (23);
-    case    30: return GET_LOOPS (30);
-    case    40: return GET_LOOPS (40);
-    case    50: return GET_LOOPS (50);
-    case    60: return GET_LOOPS (60);
-    case   100: return GET_LOOPS (100);
-    case   101: return GET_LOOPS (101);
-    case   110: return GET_LOOPS (110);
-    case   111: return GET_LOOPS (111);
-    case   112: return GET_LOOPS (112);
-    case   120: return GET_LOOPS (120);
-    case   121: return GET_LOOPS (121);
-    case   122: return GET_LOOPS (122);
-    case   124: return GET_LOOPS (124);
-    case   130: return GET_LOOPS (130);
-    case   131: return GET_LOOPS (131);
-    case   132: return GET_LOOPS (132);
-    case   133: return GET_LOOPS (133);
-    case   140: return GET_LOOPS (140);
-    case   141: return GET_LOOPS (141);
-    case   150: return GET_LOOPS (150);
-    case   160: return GET_LOOPS (160);
-    case   190: return GET_LOOPS (190);
-    case   200: return GET_LOOPS (200);
-    case   300: return GET_LOOPS (300);
-    case   400: return GET_LOOPS (400);
-    case   500: return GET_LOOPS (500);
-    case   501: return GET_LOOPS (501);
-    case   900: return GET_LOOPS (900);
-    case   910: return GET_LOOPS (910);
-    case  1000: return GET_LOOPS (1000);
-    case  1100: return GET_LOOPS (1100);
-    case  1400: return GET_LOOPS (1400);
-    case  1410: return GET_LOOPS (1410);
-    case  1420: return GET_LOOPS (1420);
-    case  1421: return GET_LOOPS (1421);
-    case  1430: return GET_LOOPS (1430);
-    case  1440: return GET_LOOPS (1440);
-    case  1441: return GET_LOOPS (1441);
-    case  1450: return GET_LOOPS (1450);
-    case  1460: return GET_LOOPS (1460);
-    case  1500: return GET_LOOPS (1500);
-    case  1600: return GET_LOOPS (1600);
-    case  1700: return GET_LOOPS (1700);
-    case  1710: return GET_LOOPS (1710);
-    case  1711: return GET_LOOPS (1711);
-    case  1720: return GET_LOOPS (1720);
-    case  1722: return GET_LOOPS (1722);
-    case  1730: return GET_LOOPS (1730);
-    case  1731: return GET_LOOPS (1731);
-    case  1740: return GET_LOOPS (1740);
-    case  1750: return GET_LOOPS (1750);
-    case  1760: return GET_LOOPS (1760);
-    case  1800: return GET_LOOPS (1800);
-    case  2100: return GET_LOOPS (2100);
-    case  2400: return GET_LOOPS (2400);
-    case  2410: return GET_LOOPS (2410);
-    case  2500: return GET_LOOPS (2500);
-    case  2600: return GET_LOOPS (2600);
-    case  2611: return GET_LOOPS (2611);
-    case  2612: return GET_LOOPS (2612);
-    case  2711: return GET_LOOPS (2711);
-    case  2811: return GET_LOOPS (2811);
-    case  3000: return GET_LOOPS (3000);
-    case  3100: return GET_LOOPS (3100);
-    case  3200: return GET_LOOPS (3200);
-    case  3710: return GET_LOOPS (3710);
-    case  3711: return GET_LOOPS (3711);
-    case  3800: return GET_LOOPS (3800);
-    case  4300: return GET_LOOPS (4300);
-    case  4400: return GET_LOOPS (4400);
-    case  4500: return GET_LOOPS (4500);
-    case  4700: return GET_LOOPS (4700);
-    case  4800: return GET_LOOPS (4800);
-    case  4900: return GET_LOOPS (4900);
-    case  5000: return GET_LOOPS (5000);
-    case  5100: return GET_LOOPS (5100);
-    case  5200: return GET_LOOPS (5200);
-    case  5300: return GET_LOOPS (5300);
-    case  5400: return GET_LOOPS (5400);
-    case  5500: return GET_LOOPS (5500);
-    case  5600: return GET_LOOPS (5600);
-    case  5700: return GET_LOOPS (5700);
-    case  5800: return GET_LOOPS (5800);
-    case  6000: return GET_LOOPS (6000);
-    case  6100: return GET_LOOPS (6100);
-    case  6211: return GET_LOOPS (6211);
-    case  6212: return GET_LOOPS (6212);
-    case  6213: return GET_LOOPS (6213);
-    case  6221: return GET_LOOPS (6221);
-    case  6222: return GET_LOOPS (6222);
-    case  6223: return GET_LOOPS (6223);
-    case  6231: return GET_LOOPS (6231);
-    case  6232: return GET_LOOPS (6232);
-    case  6233: return GET_LOOPS (6233);
-    case  6241: return GET_LOOPS (6241);
-    case  6242: return GET_LOOPS (6242);
-    case  6243: return GET_LOOPS (6243);
-    case  6300: return GET_LOOPS (6300);
-    case  6400: return GET_LOOPS (6400);
-    case  6500: return GET_LOOPS (6500);
-    case  6600: return GET_LOOPS (6600);
-    case  6700: return GET_LOOPS (6700);
-    case  6800: return GET_LOOPS (6800);
-    case  6900: return GET_LOOPS (6900);
-    case  7100: return GET_LOOPS (7100);
-    case  7200: return GET_LOOPS (7200);
-    case  7300: return GET_LOOPS (7300);
-    case  7400: return GET_LOOPS (7400);
-    case  7500: return GET_LOOPS (7500);
-    case  7600: return GET_LOOPS (7600);
-    case  7700: return GET_LOOPS (7700);
-    case  7800: return GET_LOOPS (7800);
-    case  7900: return GET_LOOPS (7900);
-    case  8000: return GET_LOOPS (8000);
-    case  8100: return GET_LOOPS (8100);
-    case  8200: return GET_LOOPS (8200);
-    case  8300: return GET_LOOPS (8300);
-    case  8400: return GET_LOOPS (8400);
-    case  8500: return GET_LOOPS (8500);
-    case  8600: return GET_LOOPS (8600);
-    case  8700: return GET_LOOPS (8700);
-    case  8800: return GET_LOOPS (8800);
-    case  8900: return GET_LOOPS (8900);
-    case  9000: return GET_LOOPS (9000);
-    case  9100: return GET_LOOPS (9100);
-    case  9200: return GET_LOOPS (9200);
-    case  9300: return GET_LOOPS (9300);
-    case  9400: return GET_LOOPS (9400);
-    case  9500: return GET_LOOPS (9500);
-    case  9600: return GET_LOOPS (9600);
-    case  9700: return GET_LOOPS (9700);
-    case  9710: return GET_LOOPS (9710);
-    case  9720: return GET_LOOPS (9720);
-    case  9800: return GET_LOOPS (9800);
-    case  9810: return GET_LOOPS (9810);
-    case  9820: return GET_LOOPS (9820);
-    case  9900: return GET_LOOPS (9900);
-    case 10000: return GET_LOOPS (10000);
-    case 10100: return GET_LOOPS (10100);
-    case 10200: return GET_LOOPS (10200);
-    case 10300: return GET_LOOPS (10300);
-    case 10400: return GET_LOOPS (10400);
-    case 10410: return GET_LOOPS (10410);
-    case 10420: return GET_LOOPS (10420);
-    case 10500: return GET_LOOPS (10500);
-    case 10600: return GET_LOOPS (10600);
-    case 10700: return GET_LOOPS (10700);
-    case 10800: return GET_LOOPS (10800);
-    case 10900: return GET_LOOPS (10900);
-    case 11000: return GET_LOOPS (11000);
-    case 11100: return GET_LOOPS (11100);
-    case 11200: return GET_LOOPS (11200);
-    case 11300: return GET_LOOPS (11300);
-    case 11400: return GET_LOOPS (11400);
-    case 11500: return GET_LOOPS (11500);
-    case 11600: return GET_LOOPS (11600);
-    case 11700: return GET_LOOPS (11700);
-    case 11800: return GET_LOOPS (11800);
-    case 11900: return GET_LOOPS (11900);
-    case 12000: return GET_LOOPS (12000);
-    case 12100: return GET_LOOPS (12100);
-    case 12200: return GET_LOOPS (12200);
-    case 12300: return GET_LOOPS (12300);
-    case 12400: return GET_LOOPS (12400);
-    case 12500: return GET_LOOPS (12500);
-    case 12600: return GET_LOOPS (12600);
-    case 12700: return GET_LOOPS (12700);
-    case 12800: return GET_LOOPS (12800);
-    case 12900: return GET_LOOPS (12900);
-    case 13000: return GET_LOOPS (13000);
-  }
+  myfree (device_name_nospace);
 
-  return 0;
+  return entry;
 }
 
 /**
@@ -9339,14 +9363,13 @@ uint set_kernel_loops (uint hash_mode)
 
 uint parse_and_store_salt (char *out, char *in, uint salt_len)
 {
-  u8 tmp[256];
+  u8 tmp[256] = { 0 };
 
   if (salt_len > sizeof (tmp))
   {
     return UINT_MAX;
   }
 
-  memset (tmp, 0, sizeof (tmp));
   memcpy (tmp, in, salt_len);
 
   if (data.opts_type & OPTS_TYPE_ST_HEX)
@@ -9479,9 +9502,7 @@ int bcrypt_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   salt->salt_len = salt_len;
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   base64_decode (bf64_to_int, (const u8 *) salt_pos, 22, tmp_buf);
 
@@ -9520,9 +9541,7 @@ int cisco4_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   u32 *digest = (u32 *) hash_buf->digest;
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   base64_decode (itoa64_to_int, (const u8 *) input_buf, 43, tmp_buf);
 
@@ -9709,7 +9728,7 @@ int netscreen_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   // unscramble
 
-  char clean_input_buf[32];
+  char clean_input_buf[32] = { 0 };
 
   char sig[6] = { 'n', 'r', 'c', 's', 't', 'n' };
   int  pos[6] = {   0,   6,  12,  17,  23,  29 };
@@ -10044,17 +10063,10 @@ int psafe2_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
     exit (-1);
   }
 
-  typedef struct
-  {
-    u32 random[2];
-    u32 hash[5];
-    u32 salt[5];   // unused, but makes better valid check
-    u32 iv[2];     // unused, but makes better valid check
-
-  } psafe2_hdr;
-
   psafe2_hdr buf;
 
+  memset (&buf, 0, sizeof (psafe2_hdr));
+
   int n = fread (&buf, sizeof (psafe2_hdr), 1, fp);
 
   fclose (fp);
@@ -10321,9 +10333,7 @@ int episerver_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   salt->salt_len = salt_len;
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   base64_decode (base64_to_int, (const u8 *) hash_pos, 27, tmp_buf);
 
@@ -10365,9 +10375,7 @@ int descrypt_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   salt->salt_len = 2;
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   base64_decode (itoa64_to_int, (const u8 *) input_buf + 2, 11, tmp_buf);
 
@@ -10806,7 +10814,7 @@ int netntlmv1_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   /* special case, last 8 byte do not need to be checked since they are brute-forced next */
 
-  uint digest_tmp[2];
+  uint digest_tmp[2] = { 0 };
 
   digest_tmp[0] = hex_to_u32 ((const u8 *) &hash_pos[32]);
   digest_tmp[1] = hex_to_u32 ((const u8 *) &hash_pos[40]);
@@ -10820,26 +10828,16 @@ int netntlmv1_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
   {
     if ((netntlm->chall_buf[2] == 0) && (netntlm->chall_buf[3] == 0) && (netntlm->chall_buf[4] == 0) && (netntlm->chall_buf[5] == 0))
     {
-      uint w[16];
+      uint w[16] = { 0 };
 
       w[ 0] = netntlm->chall_buf[6];
       w[ 1] = netntlm->chall_buf[7];
       w[ 2] = netntlm->chall_buf[0];
       w[ 3] = netntlm->chall_buf[1];
       w[ 4] = 0x80;
-      w[ 5] = 0;
-      w[ 6] = 0;
-      w[ 7] = 0;
-      w[ 8] = 0;
-      w[ 9] = 0;
-      w[10] = 0;
-      w[11] = 0;
-      w[12] = 0;
-      w[13] = 0;
       w[14] = 16 * 8;
-      w[15] = 0;
 
-      uint dgst[4];
+      uint dgst[4] = { 0 };
 
       dgst[0] = MAGIC_A;
       dgst[1] = MAGIC_B;
@@ -10862,8 +10860,8 @@ int netntlmv1_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
     transform_netntlmv1_key ((u8 *) key_md4, (u8 *) key_des);
 
-    uint Kc[16];
-    uint Kd[16];
+    uint Kc[16] = { 0 };
+    uint Kd[16] = { 0 };
 
     _des_keysetup (key_des, Kc, Kd, c_skb);
 
@@ -11383,9 +11381,7 @@ int ipb2_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   char *salt_buf = input_buf + 32 + 1;
 
-  uint salt_pc_block[16];
-
-  memset (salt_pc_block, 0, sizeof (salt_pc_block));
+  uint salt_pc_block[16] = { 0 };
 
   char *salt_pc_block_ptr = (char *) salt_pc_block;
 
@@ -11397,12 +11393,7 @@ int ipb2_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   salt_pc_block[14] = salt_len * 8;
 
-  uint salt_pc_digest[4];
-
-  salt_pc_digest[0] = MAGIC_A;
-  salt_pc_digest[1] = MAGIC_B;
-  salt_pc_digest[2] = MAGIC_C;
-  salt_pc_digest[3] = MAGIC_D;
+  uint salt_pc_digest[4] = { MAGIC_A, MAGIC_B, MAGIC_C, MAGIC_D };
 
   md5_64 (salt_pc_block, salt_pc_digest);
 
@@ -11515,9 +11506,7 @@ int sha1b64_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   u32 *digest = (u32 *) hash_buf->digest;
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   base64_decode (base64_to_int, (const u8 *) input_buf + 5, input_len - 5, tmp_buf);
 
@@ -11548,9 +11537,7 @@ int sha1b64s_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   salt_t *salt = hash_buf->salt;
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   int tmp_len = base64_decode (base64_to_int, (const u8 *) input_buf + 6, input_len - 6, tmp_buf);
 
@@ -12098,7 +12085,7 @@ int ikepsk_md5_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   char *in_off[9];
 
-  size_t in_len[9];
+  size_t in_len[9] = { 0 };
 
   in_off[0] = strtok (input_buf, ":");
 
@@ -12115,9 +12102,7 @@ int ikepsk_md5_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
     in_len[i] = strlen (in_off[i]);
   }
 
-  char *ptr;
-
-  ptr = (char *) ikepsk->msg_buf;
+  char *ptr = (char *) ikepsk->msg_buf;
 
   for (i = 0; i < in_len[0]; i += 2) *ptr++ = hex_to_u8 ((const u8 *) in_off[0] + i);
   for (i = 0; i < in_len[1]; i += 2) *ptr++ = hex_to_u8 ((const u8 *) in_off[1] + i);
@@ -12185,7 +12170,7 @@ int ikepsk_sha1_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   char *in_off[9];
 
-  size_t in_len[9];
+  size_t in_len[9] = { 0 };
 
   in_off[0] = strtok (input_buf, ":");
 
@@ -12202,9 +12187,7 @@ int ikepsk_sha1_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
     in_len[i] = strlen (in_off[i]);
   }
 
-  char *ptr;
-
-  ptr = (char *) ikepsk->msg_buf;
+  char *ptr = (char *) ikepsk->msg_buf;
 
   for (i = 0; i < in_len[0]; i += 2) *ptr++ = hex_to_u8 ((const u8 *) in_off[0] + i);
   for (i = 0; i < in_len[1]; i += 2) *ptr++ = hex_to_u8 ((const u8 *) in_off[1] + i);
@@ -12356,7 +12339,7 @@ int truecrypt_parse_hash_1k (char *input_buf, uint input_len, hash_t *hash_buf)
     exit (-1);
   }
 
-  char buf[512];
+  char buf[512] = { 0 };
 
   int n = fread (buf, 1, sizeof (buf), fp);
 
@@ -12403,7 +12386,7 @@ int truecrypt_parse_hash_2k (char *input_buf, uint input_len, hash_t *hash_buf)
     exit (-1);
   }
 
-  char buf[512];
+  char buf[512] = { 0 };
 
   int n = fread (buf, 1, sizeof (buf), fp);
 
@@ -12960,9 +12943,7 @@ int episerver4_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   salt->salt_len = salt_len;
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   base64_decode (base64_to_int, (const u8 *) hash_pos, 43, tmp_buf);
 
@@ -13063,9 +13044,7 @@ int sha512b64s_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   salt_t *salt = hash_buf->salt;
 
-  u8 tmp_buf[120];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[120] = { 0 };
 
   int tmp_len = base64_decode (base64_to_int, (const u8 *) input_buf + 9, input_len - 9, tmp_buf);
 
@@ -13941,9 +13920,7 @@ int nsec3_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
   // and one that includes only the real salt (stored into salt_buf[]).
   // the domain-name length is put into array position 7 of salt_buf_pc[] since there is not salt_pc_len
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   base32_decode (itoa32_to_int, (const u8 *) hashbuf_pos, 32, tmp_buf);
 
@@ -14143,9 +14120,7 @@ int lotus6_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   salt_t *salt = hash_buf->salt;
 
-  u8 tmp_buf[120];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[120] = { 0 };
 
   base64_decode (lotus64_to_int, (const u8 *) input_buf + 2, input_len - 3, tmp_buf);
 
@@ -14174,9 +14149,7 @@ int lotus8_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   salt_t *salt = hash_buf->salt;
 
-  u8 tmp_buf[120];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[120] = { 0 };
 
   base64_decode (lotus64_to_int, (const u8 *) input_buf + 2, input_len - 3, tmp_buf);
 
@@ -14190,7 +14163,7 @@ int lotus8_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   // iteration
 
-  char tmp_iter_buf[11];
+  char tmp_iter_buf[11] = { 0 };
 
   memcpy (tmp_iter_buf, tmp_buf + 16, 10);
 
@@ -14363,9 +14336,7 @@ int peoplesoft_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   u32 *digest = (u32 *) hash_buf->digest;
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   base64_decode (base64_to_int, (const u8 *) input_buf, input_len, tmp_buf);
 
@@ -14586,9 +14557,7 @@ int scrypt_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   // base64 decode
 
-  u8 tmp_buf[33];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[33] = { 0 };
 
   int tmp_len = base64_decode (base64_to_int, (const u8 *) saltbuf_pos, hash_pos - saltbuf_pos, tmp_buf);
 
@@ -14626,7 +14595,7 @@ int juniper_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
    * parse line
    */
 
-  char decrypted[76]; // iv + hash
+  char decrypted[76] = { 0 }; // iv + hash
 
   juniper_decrypt_hash (input_buf, decrypted);
 
@@ -14700,9 +14669,7 @@ int cisco8_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   // base64 decode hash
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   uint hash_len = input_len - 3 - salt_len - 1;
 
@@ -14760,9 +14727,7 @@ int cisco9_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   // base64 decode hash
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   uint hash_len = input_len - 3 - salt_len - 1;
 
@@ -15885,9 +15850,7 @@ int djangopbkdf2_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   // base64 decode hash
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   uint hash_len = input_len - (hash_pos - input_buf);
 
@@ -15979,9 +15942,7 @@ int crammd5_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   // base64 decode salt
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   salt_len = base64_decode (base64_to_int, (const u8 *) salt_pos, salt_len, tmp_buf);
 
@@ -16059,9 +16020,7 @@ int saph_sha1_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   u32 base64_len = input_len - (base64_pos - input_buf);
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   u32 decoded_len = base64_decode (base64_to_int, (const u8 *) base64_pos, base64_len, tmp_buf);
 
@@ -16798,14 +16757,14 @@ int pdf14_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   // md5
 
-  uint salt_pc_block[32];
+  uint salt_pc_block[32] = { 0 };
 
   char *salt_pc_ptr = (char *) salt_pc_block;
 
   memcpy (salt_pc_ptr, padding, 32);
   memcpy (salt_pc_ptr + 32, pdf->id_buf, pdf->id_len);
 
-  uint salt_pc_digest[4];
+  uint salt_pc_digest[4] = { 0 };
 
   md5_complete_no_limit (salt_pc_digest, salt_pc_block, 32 + pdf->id_len);
 
@@ -17095,9 +17054,7 @@ int pbkdf2_sha256_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   // decode hash
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   int hash_len = base64_decode (base64_to_int, (const u8 *) hash_pos, hash_b64_len, tmp_buf);
 
@@ -17439,9 +17396,8 @@ int sip_auth_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   // work with a temporary copy of input_buf (s.t. we can manipulate it directly)
 
-  char temp_input_buf[input_len + 1];
+  char *temp_input_buf = (char *) mymalloc (input_len + 1);
 
-  memset (temp_input_buf, 0, sizeof (temp_input_buf));
   memcpy (temp_input_buf, input_buf, input_len);
 
   // URI_server:
@@ -17450,177 +17406,307 @@ int sip_auth_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   char *URI_client_pos = strchr (URI_server_pos, '*');
 
-  if (URI_client_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+  if (URI_client_pos == NULL)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SEPARATOR_UNMATCHED);
+  }
 
   URI_client_pos[0] = 0;
   URI_client_pos++;
 
   uint URI_server_len = strlen (URI_server_pos);
 
-  if (URI_server_len > 512) return (PARSER_SALT_LENGTH);
+  if (URI_server_len > 512)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SALT_LENGTH);
+  }
 
   // URI_client:
 
   char *user_pos = strchr (URI_client_pos, '*');
 
-  if (user_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+  if (user_pos == NULL)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SEPARATOR_UNMATCHED);
+  }
 
   user_pos[0] = 0;
   user_pos++;
 
   uint URI_client_len = strlen (URI_client_pos);
 
-  if (URI_client_len > 512) return (PARSER_SALT_LENGTH);
+  if (URI_client_len > 512)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SALT_LENGTH);
+  }
 
   // user:
 
   char *realm_pos = strchr (user_pos, '*');
 
-  if (realm_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+  if (realm_pos == NULL)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SEPARATOR_UNMATCHED);
+  }
 
   realm_pos[0] = 0;
   realm_pos++;
 
   uint user_len = strlen (user_pos);
 
-  if (user_len > 116) return (PARSER_SALT_LENGTH);
+  if (user_len > 116)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SALT_LENGTH);
+  }
 
   // realm:
 
   char *method_pos = strchr (realm_pos, '*');
 
-  if (method_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+  if (method_pos == NULL)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SEPARATOR_UNMATCHED);
+  }
 
   method_pos[0] = 0;
   method_pos++;
 
   uint realm_len = strlen (realm_pos);
 
-  if (realm_len > 116) return (PARSER_SALT_LENGTH);
+  if (realm_len > 116)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SALT_LENGTH);
+  }
 
   // method:
 
   char *URI_prefix_pos = strchr (method_pos, '*');
 
-  if (URI_prefix_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+  if (URI_prefix_pos == NULL)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SEPARATOR_UNMATCHED);
+  }
 
   URI_prefix_pos[0] = 0;
   URI_prefix_pos++;
 
   uint method_len = strlen (method_pos);
 
-  if (method_len > 246) return (PARSER_SALT_LENGTH);
+  if (method_len > 246)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SALT_LENGTH);
+  }
 
   // URI_prefix:
 
   char *URI_resource_pos = strchr (URI_prefix_pos, '*');
 
-  if (URI_resource_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+  if (URI_resource_pos == NULL)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SEPARATOR_UNMATCHED);
+  }
 
   URI_resource_pos[0] = 0;
   URI_resource_pos++;
 
   uint URI_prefix_len = strlen (URI_prefix_pos);
 
-  if (URI_prefix_len > 245) return (PARSER_SALT_LENGTH);
+  if (URI_prefix_len > 245)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SALT_LENGTH);
+  }
 
   // URI_resource:
 
   char *URI_suffix_pos = strchr (URI_resource_pos, '*');
 
-  if (URI_suffix_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+  if (URI_suffix_pos == NULL)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SEPARATOR_UNMATCHED);
+  }
 
   URI_suffix_pos[0] = 0;
   URI_suffix_pos++;
 
   uint URI_resource_len = strlen (URI_resource_pos);
 
-  if (URI_resource_len <   1) return (PARSER_SALT_LENGTH);
-  if (URI_resource_len > 246) return (PARSER_SALT_LENGTH);
+  if (URI_resource_len < 1 || URI_resource_len > 246)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SALT_LENGTH);
+  }
 
   // URI_suffix:
 
   char *nonce_pos = strchr (URI_suffix_pos, '*');
 
-  if (nonce_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+  if (nonce_pos == NULL)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SEPARATOR_UNMATCHED);
+  }
 
   nonce_pos[0] = 0;
   nonce_pos++;
 
   uint URI_suffix_len = strlen (URI_suffix_pos);
 
-  if (URI_suffix_len > 245) return (PARSER_SALT_LENGTH);
+  if (URI_suffix_len > 245)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SALT_LENGTH);
+  }
 
   // nonce:
 
   char *nonce_client_pos = strchr (nonce_pos, '*');
 
-  if (nonce_client_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+  if (nonce_client_pos == NULL)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SEPARATOR_UNMATCHED);
+  }
 
   nonce_client_pos[0] = 0;
   nonce_client_pos++;
 
   uint nonce_len = strlen (nonce_pos);
 
-  if (nonce_len <  1) return (PARSER_SALT_LENGTH);
-  if (nonce_len > 50) return (PARSER_SALT_LENGTH);
+  if (nonce_len < 1 || nonce_len > 50)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SALT_LENGTH);
+  }
 
   // nonce_client:
 
   char *nonce_count_pos = strchr (nonce_client_pos, '*');
 
-  if (nonce_count_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+  if (nonce_count_pos == NULL)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SEPARATOR_UNMATCHED);
+  }
 
   nonce_count_pos[0] = 0;
   nonce_count_pos++;
 
   uint nonce_client_len = strlen (nonce_client_pos);
 
-  if (nonce_client_len > 50) return (PARSER_SALT_LENGTH);
+  if (nonce_client_len > 50)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SALT_LENGTH);
+  }
 
   // nonce_count:
 
   char *qop_pos = strchr (nonce_count_pos, '*');
 
-  if (qop_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+  if (qop_pos == NULL)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SEPARATOR_UNMATCHED);
+  }
 
   qop_pos[0] = 0;
   qop_pos++;
 
   uint nonce_count_len = strlen (nonce_count_pos);
 
-  if (nonce_count_len > 50) return (PARSER_SALT_LENGTH);
+  if (nonce_count_len > 50)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SALT_LENGTH);
+  }
 
   // qop:
 
   char *directive_pos = strchr (qop_pos, '*');
 
-  if (directive_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+  if (directive_pos == NULL)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SEPARATOR_UNMATCHED);
+  }
 
   directive_pos[0] = 0;
   directive_pos++;
 
   uint qop_len = strlen (qop_pos);
 
-  if (qop_len > 50) return (PARSER_SALT_LENGTH);
+  if (qop_len > 50)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SALT_LENGTH);
+  }
 
   // directive
 
   char *digest_pos = strchr (directive_pos, '*');
 
-  if (digest_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+  if (digest_pos == NULL)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SEPARATOR_UNMATCHED);
+  }
 
   digest_pos[0] = 0;
   digest_pos++;
 
   uint directive_len = strlen (directive_pos);
 
-  if (directive_len != 3) return (PARSER_SALT_LENGTH);
+  if (directive_len != 3)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SALT_LENGTH);
+  }
 
   if (memcmp (directive_pos, "MD5", 3))
   {
     log_info ("ERROR: only the MD5 directive is currently supported\n");
 
+    myfree (temp_input_buf);
+
     return (PARSER_SIP_AUTH_DIRECTIVE);
   }
 
@@ -17634,9 +17720,7 @@ int sip_auth_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   uint md5_remaining_len = md5_max_len;
 
-  uint tmp_md5_buf[md5_max_len / 4];
-
-  memset (tmp_md5_buf, 0, sizeof (tmp_md5_buf));
+  uint tmp_md5_buf[64] = { 0 };
 
   char *tmp_md5_ptr = (char *) tmp_md5_buf;
 
@@ -17671,7 +17755,7 @@ int sip_auth_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
     md5_len += 1 + URI_suffix_len;
   }
 
-  uint tmp_digest[4];
+  uint tmp_digest[4] = { 0 };
 
   md5_complete_no_limit (tmp_digest, tmp_md5_buf, md5_len);
 
@@ -17696,7 +17780,12 @@ int sip_auth_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
   {
     esalt_len = 1 + nonce_len + 1 + nonce_count_len + 1 + nonce_client_len + 1 + qop_len + 1 + 32;
 
-    if (esalt_len > max_esalt_len) return (PARSER_SALT_LENGTH);
+    if (esalt_len > max_esalt_len)
+    {
+      myfree (temp_input_buf);
+
+      return (PARSER_SALT_LENGTH);
+    }
 
     snprintf (esalt_buf_ptr, max_esalt_len, ":%s:%s:%s:%s:%08x%08x%08x%08x",
       nonce_pos,
@@ -17712,7 +17801,12 @@ int sip_auth_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
   {
     esalt_len = 1 + nonce_len + 1 + 32;
 
-    if (esalt_len > max_esalt_len) return (PARSER_SALT_LENGTH);
+    if (esalt_len > max_esalt_len)
+    {
+      myfree (temp_input_buf);
+
+      return (PARSER_SALT_LENGTH);
+    }
 
     snprintf (esalt_buf_ptr, max_esalt_len, ":%s:%08x%08x%08x%08x",
       nonce_pos,
@@ -17738,7 +17832,12 @@ int sip_auth_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   uint max_salt_len = 119;
 
-  if (salt_len > max_salt_len) return (PARSER_SALT_LENGTH);
+  if (salt_len > max_salt_len)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SALT_LENGTH);
+  }
 
   snprintf (sip_salt_ptr, max_salt_len + 1, "%s:%s:", user_pos, realm_pos);
 
@@ -17777,6 +17876,8 @@ int sip_auth_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
   digest[2] = byte_swap_32 (digest[2]);
   digest[3] = byte_swap_32 (digest[3]);
 
+  myfree (temp_input_buf);
+
   return (PARSER_OK);
 }
 
@@ -18115,9 +18216,7 @@ int pbkdf2_md5_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   // decode hash
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   int hash_len = base64_decode (base64_to_int, (const u8 *) hash_pos, hash_b64_len, tmp_buf);
 
@@ -18199,9 +18298,7 @@ int pbkdf2_sha1_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   // decode hash
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   int hash_len = base64_decode (base64_to_int, (const u8 *) hash_pos, hash_b64_len, tmp_buf);
 
@@ -18288,9 +18385,7 @@ int pbkdf2_sha512_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   // decode hash
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   int hash_len = base64_decode (base64_to_int, (const u8 *) hash_pos, hash_b64_len, tmp_buf);
 
@@ -18408,9 +18503,7 @@ int bsdicrypt_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   salt->salt_len = 4;
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   base64_decode (itoa64_to_int, (const u8 *) input_buf + 9, 11, tmp_buf);
 
@@ -18609,6 +18702,102 @@ int rar5_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
   return (PARSER_OK);
 }
 
+int krb5tgs_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
+{
+  if ((input_len < DISPLAY_LEN_MIN_13100) || (input_len > DISPLAY_LEN_MAX_13100)) return (PARSER_GLOBAL_LENGTH);
+
+  if (memcmp (SIGNATURE_KRB5TGS, input_buf, 11)) return (PARSER_SIGNATURE_UNMATCHED);
+
+  u32 *digest = (u32 *) hash_buf->digest;
+
+  salt_t *salt = hash_buf->salt;
+
+  krb5tgs_t *krb5tgs = (krb5tgs_t *) hash_buf->esalt;
+
+  /**
+   * parse line
+   */
+
+  /* Skip '$' */
+  char *account_pos = input_buf + 11 + 1; 
+  
+  char *data_pos;
+
+  uint data_len;
+
+  if (account_pos[0] == '*')
+  {
+    account_pos++;
+
+    data_pos = strchr (account_pos, '*');
+
+    /* Skip '*' */
+    data_pos++;
+
+    if (data_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+
+    uint account_len = data_pos - account_pos + 1;
+
+    if (account_len >= 512) return (PARSER_SALT_LENGTH);
+
+    /* Skip '$' */
+    data_pos++;
+
+    data_len = input_len - 11 - 1 - account_len - 2;
+
+    memcpy (krb5tgs->account_info, account_pos - 1, account_len);
+  }
+  else
+  {
+    /* assume $krb5tgs$23$checksum$edata2 */
+    data_pos = account_pos;
+
+    memcpy (krb5tgs->account_info, "**", 3);
+
+    data_len = input_len - 11 - 1 - 1;
+  }
+
+  if (data_len < ((16 + 32) * 2)) return (PARSER_SALT_LENGTH);
+
+  char *checksum_ptr = (char *) krb5tgs->checksum;
+
+  for (uint i = 0; i < 16 * 2; i += 2)
+  {
+    const char p0 = data_pos[i + 0];
+    const char p1 = data_pos[i + 1];
+
+    *checksum_ptr++ = hex_convert (p1) << 0
+                     | hex_convert (p0) << 4;
+  }
+
+  char *edata_ptr = (char *) krb5tgs->edata2;
+
+  /* skip '$' */
+  for (uint i = 16 * 2 + 1; i < input_len; i += 2)
+  {
+    const char p0 = data_pos[i + 0];
+    const char p1 = data_pos[i + 1];
+    *edata_ptr++ = hex_convert (p1) << 0
+                    | hex_convert (p0) << 4;
+  }
+  
+  krb5tgs->edata2_len = strlen(edata_ptr - input_len)/(2 * 4);
+
+  salt->salt_buf[0] = krb5tgs->checksum[0];
+  salt->salt_buf[1] = krb5tgs->checksum[1];
+  salt->salt_buf[2] = krb5tgs->checksum[2];
+  salt->salt_buf[3] = krb5tgs->checksum[3];
+  
+  salt->salt_len = 32;
+
+  digest[0] = krb5tgs->checksum[0];
+  digest[1] = krb5tgs->checksum[1];
+  digest[2] = krb5tgs->checksum[2];
+  digest[3] = krb5tgs->checksum[3];
+
+  return (PARSER_OK);
+}
+
 int cf10_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 {
   if ((input_len < DISPLAY_LEN_MIN_12600) || (input_len > DISPLAY_LEN_MAX_12600)) return (PARSER_GLOBAL_LENGTH);
@@ -18644,7 +18833,7 @@ int cf10_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
    * we can precompute the first sha256 transform
    */
 
-  uint w[16];
+  uint w[16] = { 0 };
 
   w[ 0] = byte_swap_32 (salt->salt_buf[ 0]);
   w[ 1] = byte_swap_32 (salt->salt_buf[ 1]);
@@ -18663,16 +18852,7 @@ int cf10_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
   w[14] = byte_swap_32 (salt->salt_buf[14]);
   w[15] = byte_swap_32 (salt->salt_buf[15]);
 
-  uint pc256[8];
-
-  pc256[0] = SHA256M_A;
-  pc256[1] = SHA256M_B;
-  pc256[2] = SHA256M_C;
-  pc256[3] = SHA256M_D;
-  pc256[4] = SHA256M_E;
-  pc256[5] = SHA256M_F;
-  pc256[6] = SHA256M_G;
-  pc256[7] = SHA256M_H;
+  uint pc256[8] = { SHA256M_A, SHA256M_B, SHA256M_C, SHA256M_D, SHA256M_E, SHA256M_F, SHA256M_G, SHA256M_H };
 
   sha256_64 (w, pc256);
 
@@ -19925,7 +20105,7 @@ int mangle_dupeblock_prepend (char arr[BLOCK_SIZE], int arr_len, int ulen)
 
   if ((arr_len + ulen) >= BLOCK_SIZE) return (arr_len);
 
-  char cs[100];
+  char cs[100] = { 0 };
 
   memcpy (cs, arr, ulen);
 
@@ -20183,13 +20363,13 @@ int generate_random_rule (char rule_buf[RP_RULE_BUFSIZ], u32 rp_gen_func_min, u3
 
 int _old_apply_rule (char *rule, int rule_len, char in[BLOCK_SIZE], int in_len, char out[BLOCK_SIZE])
 {
-  char mem[BLOCK_SIZE];
+  char mem[BLOCK_SIZE] = { 0 };
 
   if (in == NULL) return (RULE_RC_REJECT_ERROR);
 
   if (out == NULL) return (RULE_RC_REJECT_ERROR);
 
-  if (in_len < 1) return (RULE_RC_REJECT_ERROR);
+  if (in_len < 1 || in_len > BLOCK_SIZE) return (RULE_RC_REJECT_ERROR);
 
   if (rule_len < 1) return (RULE_RC_REJECT_ERROR);
 
@@ -20202,7 +20382,7 @@ int _old_apply_rule (char *rule, int rule_len, char in[BLOCK_SIZE], int in_len,
 
   for (rule_pos = 0; rule_pos < rule_len; rule_pos++)
   {
-    int upos; int upos2;
+    int upos, upos2;
     int ulen;
 
     switch (rule[rule_pos])