[sane-devel] Current TODO list

Henning Meier-Geinitz henning@meier-geinitz.de
Thu, 3 Apr 2003 00:36:35 +0200


Hi,

On Wed, Apr 02, 2003 at 11:59:25PM +0200, Eddy De Greef wrote:
> I think I've fixed the bug that caused the mustek_pp backend to crash.
> Is there a simple way to verify this? (The tstbackend utility did not trigger
> a crash; I had to hack the backend to force a crash.)

I "created" the crash with the attached program but it seems to depend
on luck if it crashes. At least currently I can't reproduce the
crashes with mustek_pp after your changes in cvs. microtek crashes for
me and umax freezes.

Bye,
  Henning

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <dirent.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <sys/wait.h>

#include <sane/sane.h>

#define SANE_LIB_DIR "/usr/local/lib/sane/"

enum SANE_Ops
{
  OP_INIT = 0,
  OP_EXIT,
  OP_GET_DEVICES,
  OP_OPEN,
  OP_CLOSE,
  OP_STRSTATUS,
  NUM_OPS
};

static const char *op_name[] = {
  "sane_init", "sane_exit", "sane_get_devices", "sane_open", "sane_close", "sane_strstatus"
};

static void *(*op[NUM_OPS]) ();

static int got_signal = 0;

static void
sig_handler (int signal)
{
  fprintf (stderr, "got signal %d\n", signal);
  _exit (1);
}


int main ()
{
  struct stat stat_buf;
  DIR *dir;
  struct dirent *dir_entry;
  struct sigaction act;
  pid_t pid;

  if (stat (SANE_LIB_DIR, &stat_buf) < 0)
    {
      fprintf (stderr, "can't stat %s: %s\n", SANE_LIB_DIR, strerror (errno));
      return 1;
    }
  if (!S_ISDIR (stat_buf.st_mode))
    {
      fprintf (stderr, "%s is not a directory\n", SANE_LIB_DIR);
      return 1;
    }
  if ((dir = opendir (SANE_LIB_DIR)) == 0)
    {
      fprintf (stderr, "cannot read directory %s: %s\n", SANE_LIB_DIR, strerror (errno));
      return 1;
    }

  memset (&act, 0, sizeof (act));
  act.sa_handler = sig_handler;
  sigaction (SIGSEGV, &act, 0);
      
  while ((dir_entry = readdir (dir)) != 0)
    {
      char libpath[PATH_MAX];
      void *dl_handle;
      int i;
      SANE_Status status;
      SANE_Int version_code;
      const SANE_Device **device_list;

      got_signal = 0;
      if ((strlen (dir_entry->d_name) < strlen ("libsane.so")) 
	  || (strncmp ("libsane", dir_entry->d_name, strlen ("libsane")) != 0)
	  || (strncmp (dir_entry->d_name + strlen (dir_entry->d_name) - 3, ".so", 3) != 0))
	  continue;
      fprintf (stderr, "testing %s: ", dir_entry->d_name);
      sprintf (libpath, "%s%s", SANE_LIB_DIR, dir_entry->d_name);
      dl_handle = dlopen (libpath, RTLD_LAZY);
      if (!dl_handle)
	{
	  fprintf (stderr, "opening %s failed: %s\n", libpath, dlerror());
	  continue;
	}
      for (i = 0; i < NUM_OPS; i++)
	{
	  op[i] = (void *(*)(void)) dlsym (dl_handle, op_name[i]);
	  if (!op[i])
	    break;
	}
      if (i < NUM_OPS)
	{
	  fprintf (stderr, "getting symbol %s failed: %s\n", op_name[i], dlerror());
	  dlclose (dl_handle);
	  continue;
	}
      
      pid = fork ();

      if (pid == 0)
	{
	  for (i = 0; i < 10; i++)
	    {
	      SANE_Handle handle;

	      fprintf (stderr, "%d ", i);
	      status = (SANE_Status) (*op[OP_INIT]) (&version_code, 0);
	      if (status != SANE_STATUS_GOOD)
		{
		  fprintf (stderr, "sane_init failed (i = %d): %s\n", i, 
			   (SANE_String_Const) (*op[OP_STRSTATUS]) (status));
		  break;
		}
	      status = (SANE_Status) (*op[OP_GET_DEVICES]) (&device_list, SANE_FALSE);
	      if (status != SANE_STATUS_GOOD)
		{
		  fprintf (stderr, "sane_get_devices failed (i = %d): %s\n", i, 
			   (SANE_String_Const) (*op[OP_STRSTATUS]) (status));
		  break;
		}
	      status = (SANE_Status) (*op[OP_OPEN]) ("", &handle);
	      if (status == SANE_STATUS_GOOD)
		  (*op[OP_CLOSE]) (handle);

	      (*op[OP_EXIT]) ();
	    }
	  if (i < 10)
	    {
	      dlclose (dl_handle);
	      _exit (2);
	    }
	  _exit (0);
	}
      else if (pid > 0)
	{
	  int status;
	  waitpid (pid, &status, 0);
	  if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
	    fprintf (stderr, "ok\n");
	  dlclose (dl_handle);
	}
	      
    }

  fprintf (stderr, "done\n");
  return 0;
}