rrthomas / recode

Charset converter tool and library
GNU General Public License v3.0
130 stars 12 forks source link

librecode can hang for invalid conversions #52

Open bkmgit opened 9 months ago

bkmgit commented 9 months ago

When testing AnyMeal, on Fedora 38, found that the program below

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <recodext.h>

const char *program_name;

int
main (int argc, char *const *argv)
{
  program_name = argv[0];
  RECODE_OUTER outer = recode_new_outer (true);
  RECODE_REQUEST request = recode_new_request (outer);
  char input_buffer[10] = "Äpfel";
  char *output_buffer;
  size_t output_length;
  size_t input_length = 6;
  size_t output_allocated;
  bool success;

  success = recode_scan_request (request, "latin1..ascii");
  request->verbose_flag = true;
  RECODE_TASK task = recode_new_task(request);
  task->input.buffer = input_buffer;
  task->input.cursor = input_buffer;
  task->input.limit = input_buffer + input_length;
  task->output.buffer = output_buffer;
  task->output.cursor = output_buffer;
  task->output.limit = output_buffer + output_allocated;
  printf("Starting task\n");
  success = recode_perform_task (task);
  printf("Task complete\n");
  output_buffer = task->output.buffer;
  output_length = task->output.cursor - task->output.buffer;
  output_allocated = task->output.limit - task->output.buffer;
  recode_delete_task (task);
  printf("%s\n",output_buffer);
  recode_delete_request (request);
  recode_delete_outer (outer);

  exit (success ? 0 : 1);
}

hangs and does not print Task Complete. If one changes Äpfel to Apfel it works. Attempting the conversion from the command line does however issue an error message that the input is untranslatable. This is with release 3.7.14

bkmgit commented 9 months ago

The following works correctly:

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <recodext.h>

const char *program_name;

int main (int argc, char *const *argv)
{
  program_name = argv[0];
  RECODE_OUTER outer = recode_new_outer (true);
  RECODE_REQUEST request = recode_new_request (outer);
  request->verbose_flag = true;
  char input_buffer[10] = "Äpfel";
  char *output_buffer;
  size_t output_length;
  size_t input_length = 6;
  size_t output_allocated = 20;
  output_buffer = (char*)malloc(output_allocated * sizeof(char));
  bool success;

  success = recode_scan_request (request, "latin1..ascii");
  RECODE_TASK task = recode_new_task(request);
  task->fail_level = RECODE_NOT_CANONICAL;
  task->abort_level = RECODE_NOT_CANONICAL;
  task->input.buffer = input_buffer;
  task->input.cursor = input_buffer;
  task->input.limit = input_buffer + input_length;
  task->output.buffer = output_buffer;
  task->output.cursor = output_buffer;
  task->output.limit = output_buffer + output_allocated;
  printf("Starting task\n");
  success = recode_perform_task (task);
  printf("Task complete\n");
  output_buffer = task->output.buffer;
  output_length = task->output.cursor - task->output.buffer;
  output_allocated = task->output.limit - task->output.buffer;
  recode_delete_task (task);

  if (success) printf("%s\n",output_buffer);
  free(output_buffer);
  recode_delete_request (request);
  recode_delete_outer (outer);

  exit (success ? 0 : 1);
}
rrthomas commented 9 months ago

Thanks for this. I'm sorry, but my time to work on Recode is limited at present, and librecode is not a high priority. If you can provide any further analysis, I'd be most grateful; otherwise, I'll look at it when I can!