Re: 7.1 odbc bug & patch - Mailing list pgsql-patches

From Bruce Momjian
Subject Re: 7.1 odbc bug & patch
Date
Msg-id 200106111636.f5BGaQg17854@candle.pha.pa.us
Whole thread Raw
In response to 7.1 odbc bug & patch  (Dave Bodenstab <imdave@mcs.net>)
Responses RE: 7.1 odbc bug & patch
List pgsql-patches
Wow, if all our code was as bad as this ODBC snipped we be in serious
trouble.  :-)

>
> Your name               : Dave Bodenstab
> Your email address      : imdave@mcs.net
>
>
> System Configuration
> ---------------------
>   Architecture (example: Intel Pentium)         : (shouldn't matter) Intel x86
>
>   Operating System (example: Linux 2.0.26 ELF)  : (shouldn't matter) FreeBSD
>
>   PostgreSQL version (example: PostgreSQL-7.1):   PostgreSQL-7.1
>
>   Compiler used (example:  gcc 2.8.0)           : (shouldn't matter) gcc 2.7.2.1
>
>
>
> Please enter a FULL description of your problem:
> ------------------------------------------------
> I installed postgres 7.1 with --enable-odbc.  I then installed
> tclodbc (http://sourceforge.net/projects/tclodbc) and libiodbc-2.50.3
> (http://www.iodbc.org/dist/libiodbc-2.50.3.tar.gz).  I could not
> get either to work... postgres would not find the global odbcinst.ini
> file.  I traced this to src/interfaces/odbc/gpps.c -- here are the
> many things I think are wrong:
>
>  40  GetPrivateProfileString(char *theSection,        /* section name */
>   :
>  50  {
>  51      char        buf[MAXPGPATH];
>  52      char       *ptr = 0;
>   :
>  63      int            j = 0;
>
>  64      j = strlen(theIniFileName) + 1;
>  65      ptr = (char *) getpwuid(getuid());    /* get user info */
>
>  66      if (ptr == NULL)
>  67      {
>  68          if (MAXPGPATH - 1 < j)
>  69              theIniFileName[MAXPGPATH - 1] = '\0';
>
>  70          sprintf(buf, "%s", theIniFileName);
>  71      }
>  72      ptr = ((struct passwd *) ptr)->pw_dir;        /* get user home dir */
>  73      if (ptr == NULL || *ptr == '\0')
>  74          ptr = "/home";
>
>  75      /*
>  76       * This doesn't make it so we find an ini file but allows normal
>  77       * processing to continue further on down. The likelihood is that the
>  78       * file won't be found and thus the default value will be returned.
>  79       */
>  80      if (MAXPGPATH - 1 < strlen(ptr) + j)
>  81      {
>  82          if (MAXPGPATH - 1 < strlen(ptr))
>  83              ptr[MAXPGPATH - 1] = '\0';
>  84          else
>  85              theIniFileName[MAXPGPATH - 1 - strlen(ptr)] = '\0';
>  86      }
>
>  87      sprintf(buf, "%s/%s", ptr, theIniFileName);
>
>  88      /*
>  89       * This code makes it so that a file in the users home dir overrides a
>  90       * the "default" file as passed in
>  91       */
>  92      aFile = (FILE *) (buf ? fopen(buf, PG_BINARY_R) : NULL);
>  93      if (!aFile)
>  94      {
>  95          sprintf(buf, "%s", theIniFileName);
>  96          aFile = (FILE *) (buf ? fopen(buf, PG_BINARY_R) : NULL);
>  97      }
>
> + Line 65 sets ptr, line 66 checks for NULL but line 72 dereferences
>   ptr anyway.  Then line 73 checks for NULL again!?
> + Line 87 unconditionally ignores what line 70 did.
> + Lines 69, 83 and 85 modify the value passed to the function unbeknownst
>   to the calling function.  The values could be a static string or might
>   be further used by the calling function.
> + Truncating the strings might result in a string that accidently matches
>   another, totally non-related file.
> + Line 96 checks ``buf?'', but buf[] is an array and the test will *always*
>   be true.
> + The globally installed odbcinst.ini file is never checked.  This is
>   why I couldn't get things to work -- it was looking for odbcinst.ini
>   only in my home directory or the current directory.
>
>
>
> Please describe a way to repeat the problem.   Please try to provide a
> concise reproducible example, if at all possible:
> ----------------------------------------------------------------------
> Run tclodbc and do a ``database db <DSNname>'' where ``DSNname'' is
> one of the DSN's in /usr/local/etc/odbcinst.ini (or wherever the
> global ini file is installed.)  The result is always the error
> message that ``one of server,port,database,etc. are missing''.
>
> Run libiodbc-2.50.3/samples/odbctest <DSNname>.  The command fails
> to connect to the database and just exits.
>
>
>
> If you know how this problem might be fixed, list the solution below:
> ---------------------------------------------------------------------
> I couldn't find any documentation as to what the correct behavior should
> be, and the comments aren't any clearer.  I changed the code to look for
> the odbcinst.ini file in 1) $HOME, 2) the current directory and 3) the
> globally installed file.  I also fixed all the problems I mentioned
> above.  Here is the patch, it works for me.  Use it any way you want.
>
> --- gpps.c    2001/06/06 02:53:05    7.1
> +++ gpps.c    2001/06/06 17:23:39    7.1.1.3
> @@ -35,6 +35,7 @@
>  #include <string.h>
>  #include "misc.h"
>  #include "gpps.h"
> +#include "dlg_specific.h"
>
>  #ifndef TRUE
>  #define TRUE    ((BOOL)1)
> @@ -44,6 +45,12 @@
>  #endif
>
>
> +/*
> + * theIniFileName is searched for in:
> + *     $HOME/theIniFileName
> + *     theIniFileName
> + *     ODBCINST_INI
> + */
>  DWORD
>  GetPrivateProfileString(char *theSection,        /* section name */
>                          char *theKey,    /* search key name */
> @@ -68,48 +75,36 @@
>      size_t        aReturnLength = 0;
>      BOOL        aSectionFound = FALSE;
>      BOOL        aKeyFound = FALSE;
> -    int            j = 0;
>
> -    j = strlen(theIniFileName) + 1;
>      ptr = (char *) getpwuid(getuid());    /* get user info */
>
> -    if (ptr == NULL)
> -    {
> -        if (MAXPGPATH - 1 < j)
> -            theIniFileName[MAXPGPATH - 1] = '\0';
> -
> -        sprintf(buf, "%s", theIniFileName);
> -    }
> -    ptr = ((struct passwd *) ptr)->pw_dir;        /* get user home dir */
> -    if (ptr == NULL || *ptr == '\0')
> +    if (ptr == NULL || (((struct passwd *) ptr)->pw_dir) == NULL || *(((struct passwd *) ptr)->pw_dir) == '\0')
>          ptr = "/home";
> +    else
> +        ptr = ((struct passwd *) ptr)->pw_dir;        /* get user home dir */
>
>      /*
> -     * This doesn't make it so we find an ini file but allows normal
> -     * processing to continue further on down. The likelihood is that the
> -     * file won't be found and thus the default value will be returned.
> +     * If it can't be opened because the paths are too long, then
> +     * skip it, don't just truncate the path string...  The truncated path
> +     * might accidently be an existing file.  The default value will be
> +     * returned instead.
>       */
> -    if (MAXPGPATH - 1 < strlen(ptr) + j)
> +    if (MAXPGPATH - 1 >= strlen(ptr) + 1 + strlen(theIniFileName))
>      {
> -        if (MAXPGPATH - 1 < strlen(ptr))
> -            ptr[MAXPGPATH - 1] = '\0';
> -        else
> -            theIniFileName[MAXPGPATH - 1 - strlen(ptr)] = '\0';
> +        sprintf(buf, "%s/%s", ptr, theIniFileName);
> +        aFile = (FILE *) fopen(buf, PG_BINARY_R);
>      }
>
> -    sprintf(buf, "%s/%s", ptr, theIniFileName);
> -
>      /*
>       * This code makes it so that a file in the users home dir overrides a
>       * the "default" file as passed in
>       */
> -    aFile = (FILE *) (buf ? fopen(buf, PG_BINARY_R) : NULL);
>      if (!aFile)
>      {
> -        sprintf(buf, "%s", theIniFileName);
> -        aFile = (FILE *) (buf ? fopen(buf, PG_BINARY_R) : NULL);
> +        aFile = (FILE *) fopen(theIniFileName, PG_BINARY_R);
> +        if (!aFile)
> +            aFile = (FILE *) fopen(ODBCINST_INI, PG_BINARY_R);
>      }
> -
>
>      aLength = (theDefault == NULL) ? 0 : strlen(theDefault);
>
>
>
>
>
> ---------------------------(end of broadcast)---------------------------
> TIP 1: subscribe and unsubscribe commands go to majordomo@postgresql.org
>

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026

pgsql-patches by date:

Previous
From: Bruce Momjian
Date:
Subject: Re: sequence.c compile failure
Next
From: Bruce Momjian
Date:
Subject: Re: YA readline 4.2 patch