[Possible BUG]: Wine-20011108

Pavel Tsekov ptsekov at syntrex.com
Fri Dec 7 08:48:50 CST 2001


Hello, there

I've run into situation which looks like bug to me -
attached is the source and the executable, wich triggers
the buggy behaviour. The executable is compiled with
mingw32 cross-copiler based on linux and targeted to Win32.
The cross-compiler can be found at:
http://members.telering.at/jessich/mingw/mingwcross/mingw_cross.html

This is the output of the program being run with Wine on RedHat Linux
7.1:

Setting the URL base path to: file://C/Cygwin/bin/
Parsing relative URL of type file:
Authority: C
Path: Cygwin/bin//pinco/panco
fixme:msvcrt:MSVCRT_signal (11 (nil)):stub
err:seh:EXC_DefaultHandling Unhandled exception code c000013a flags 0
addr 0xffffffff

And here is the correct ouput as produced by native linux executable on
the 
same system:

Setting the URL base path to: file://C/Cygwin/bin/
Parsing relative URL of type file:
Authority: C
Path: Cygwin/bin//pinco/panco
Parsing relative URL of type cygfile:
Authority: C
Path: Cygwin/bin//bin/passwd
Parsing absolute URL of type file:
Authority: (null)
Path: usr/bin/passwd
Parsing absolute URL of type cygfile:
Authority: (null)
Path: usr/bin/passwd

With Win the trouble starts as we come to line 229 of URLParser.cc - 
trying to do malloc. Notice that the first time when it comes to this
line everything is ok - but the second time we have a trouble.

Pleass CC any replies to me since I dont follow the list.
-------------- next part --------------
/*
 * Copyright (c) 2001, Pavel Tsekov.
 *
 *     This program is free software; you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation; either version 2 of the License, or
 *     (at your option) any later version.
 *
 *     A copy of the GNU General Public License can be found at
 *     http://www.gnu.org/
 *
 * Written by Pavel Tsekov  <ptsekov at fixity.net>
 *
 */

#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#include "URLParser.h"

URLParser URLParser::baseURL;

URLParser::URLParser () : internalURL (0), internalURLlen (0), host (0),
port (0), user (0), pass (0), path (0)
{
}

URLParser::URLParser (const char *url) : internalURL (0), internalURLlen (0),
host (0), port (0), user (0), pass (0), path (0)
{
  *this = url;
}

URLParser::~URLParser ()
{
  *this = 0;
}

void
URLParser::parse ()
{
  if (internalURL == NULL || *internalURL == '\0')
    return;

  char *start, *end, *authority = NULL, *schema = NULL;
  start = internalURL;
  end = internalURL + strlen (internalURL);

  // Trim the leading and trailing whitespaces
  for (;start < end && *start == ' '; start++);
  for (;(end - 1)  >= start && *(end - 1) == ' '; end--);
  *end = '\0';

  // Split the internal URL buffer in its building parts - authority (if any)
  // and path. This are to be parsed later.
  for (char *c = start; c < end && path == NULL; c++)
    {
      if (*c == '/')
        {
          char *p;
          for (p = c; p < end && *p == '/'; p++);

          switch (p - c)
            {
              case 2: // Network path separator (p points to the start of
                      // authority)
                {
                  if (authority == NULL && *(c - 1) == ':')
                    {
                      *(c - 1) = '\0';
                      authority = p;
                    }
                  /* FIXME: There should be no // sequence in the URL, except
                            exactly after the schema separator ':', but hey...
                            We need this for relative URLs to work, atm. As
                            soon as we are sure that we handle relative URLs,
                            without leaving any sequential path separators ('/')
                            in them we can uncomment this code.
                  else // Erronous URL (maybe)
                    return;
                  */
                  break;
                }
              case 1: // Path separator (p points to the start of the path)
                {
                  // FIXME: Doesn't look quite nice :)
                  if (authority != NULL || *(c - 1) == ':')
                    {
                      if (p < end)
                        path = p;
                      else
                        path = NULL;
                      *c = '\0';
                      if (authority == NULL && *(c - 1) == ':')
                        *(c - 1) = '\0';
                    }
                  break;
                }
              /* FIXME: Read the _BIG_ comment in 'case 2:' - it's all there!
              default:
                return;
              */
            }
          c += p - c - 1;
        }
      else if (*c == ':')
        {
          if (schema == NULL)
            schema = c;
        }
    }

    parse_authority (authority);
    // This is a special case, thus it may not look nor feel very well...
    // But hey... :)
    if (authority == 0 && path == 0 && schema != 0 && *(schema + 1) != '\0')
      {
        char *backupURL = internalURL;
        internalURL = 0;
        *this = baseURL;
        internalURL = (char *) realloc (internalURL,
                                       internalURLlen + strlen (schema + 1));
        pfixup (baseURL);

        *schema = '/';
        strcat ((char *) path, schema);
        free (backupURL);
      }
}

void
URLParser::parse_authority (char *start)
{
  if (start == NULL || *start == '\0')
    return;

  char *end = (char *) path, *c;
  if (end == NULL)
    end = start + strlen (start);
    
  // Check if there is an user info embedded into the authority
  // field.
  for (c = start; c < end && *c != '@'; c++);

  char * tport = 0;
  if (*c == '@')
    {
      *c = '\0';
      parse_colon_sep_string (start, c, (char **) &user, (char **) &pass);
      parse_colon_sep_string (c + 1, end, (char **) &host, (char **) &tport);
    }
  else
    {
      parse_colon_sep_string (start, end, (char **) &host, (char **) &tport);
    }
  if (tport)
      port = abs (atoi (tport));
}

void
URLParser::parse_colon_sep_string (char *start, char *end, char **first, char **second)
{
  // FIXME: If end is NULL search upto the zero terminator.
  if (start == NULL || *start == '\0' || end == NULL)
    return;

  if (first == NULL || second == NULL)
    return;

  char *c = start;
  for (; c < end && *c != ':'; c++);

  if ((c - start) != 0)
    *first = start;

  if (*c == ':')
    {
      *c = '\0';
      if ((end - c) > 1)
        *second = c + 1;
    }
}

URLParser::Schema
URLParser::GetSchema (void) const
{
  if (!strcasecmp ("file", internalURL))
    return URLParser::file;
  if (!strcasecmp ("cygfile", internalURL))
    return URLParser::cygfile;
  if (!strcasecmp ("ftp", internalURL))
    return URLParser::ftp;
  if (!strcasecmp ("http", internalURL))
    return URLParser::http;
  return URLParser::unknown;
}

void
URLParser::operator = (const char *src)
{
  if (internalURL != 0)
    {
      if (user != NULL)
        memset ((void *) user, '\0', strlen (user));
      if (pass != NULL)
        memset ((void *) pass, '\0', strlen (pass));
      free (internalURL);
      internalURL = 0;
      internalURLlen = 0;
      host = user = pass = path = 0;
      port = 0;
    }

  if (src != 0 && *src != '\0')
    {
      internalURLlen = strlen (src) + 1;
      internalURL = strdup (src);
      parse ();
    }
}

void
URLParser::operator = (const URLParser& src)
{
  *this = 0;
  if (src.GetSchema () != URLParser::unknown)
    {
      internalURL = (char *) malloc (src.internalURLlen);
      memcpy (internalURL, src.internalURL, src.internalURLlen);
      internalURLlen = src.internalURLlen;
      port = src.port;
      pfixup (src);
    }
}

void
URLParser::pfixup (const URLParser& src)
{
  char **p;
  if (src.host != 0)
    {
      p = (char **) &host;
      *p = internalURL + (src.host - src.internalURL);
    }
  if (src.user != 0)
    {
      p = (char **) &user;
      *p = internalURL + (src.user - src.internalURL);
    }
  if (src.pass != 0)
    {
      p = (char **) &pass;
      *p = internalURL + (src.pass - src.internalURL);
    }
  if (src.path != 0)
    {
      p = (char **) &path;
      *p = internalURL + (src.path - src.internalURL);
    }
}

// Converts absolute dos path to URL path.
char *
URLParser::dos_path_to_url_path (const char *path)
{
  if (path == 0 || *path == '\0')
    return 0;

  int len = strlen (path);

  if (len < 3 || !isalpha (path[0]) || path[1] != ':' || path[2] != '\\')
    return 0;

  // The code below could be replaced by a call to concat ()
  char *rv = (char *) malloc (len + 8);
  strcpy (rv, "file://");
  rv[7] = *path;

  int i = 2;
  char *bp = rv + 8;
  for (; path[i] != '\0'; i++, bp++)
    {
      if (path[i] == '\\' || path[i] == '/')
        {
          char *p;
          for (p = (char *) &path[i]; *p != '\0' && (*p == '\\' || *p == '/'); p++);
          *bp = '/';
          i += p - &path[i] - 1;
        }
      else
        *bp = path[i];
    }
  *bp = '\0';
  return rv;
}

void
URLParser::SetBaseURL (const char *base)
{
  char *url_path = dos_path_to_url_path (base);
  baseURL = url_path;
  if (url_path)
    free (url_path);
}
-------------- next part --------------
/*
 * Copyright (c) 2001, Pavel Tsekov.
 *
 *     This program is free software; you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation; either version 2 of the License, or
 *     (at your option) any later version.
 *
 *     A copy of the GNU General Public License can be found at
 *     http://www.gnu.org/
 *
 * Written by Pavel Tsekov  <ptsekov at fixity.net>
 *
 */

#ifndef _URL_PARSER_H_
#define _URL_PARSER_H_

class URLParser
{
  static URLParser baseURL; // Support for relative URLs
  char *internalURL;
  size_t internalURLlen;
  const char *host;
  unsigned int port;
  const char *user;
  const char *pass;
  const char *path;

  // Split the URL into smaller parts for easier parsing.
  void parse ();
  // Parse the authority part of the URL (user:info at host:port).
  void parse_authority (char *start);
  // Utility for parsing the user/pass and host/port pairs.
  void parse_colon_sep_string (char *start, char *end, char **first, char **second);
  // Utility to fixup the pointers which point inside the internalURL
  void pfixup (const URLParser& src);
public:
  enum Schema { unknown = 0, file, cygfile, ftp, http };

  static void SetBaseURL (const char *base);
  static char *URLParser::dos_path_to_url_path (const char *path);

  URLParser ();
  URLParser (const char *url);
  ~URLParser ();

  void operator = (const char *);
  void operator = (const URLParser& src);

  const char *GetHost (void) const { return host; }
  unsigned int GetPort (void) const { return port; }
  const char *GetUser (void) const { return user; }
  const char *GetPass (void) const { return pass; }
  const char *GetPath (void) const { return path; } 
  Schema GetSchema (void) const;
};

#endif
-------------- next part --------------
#include <stdio.h>
#include "URLParser.h"

int main (int argc, char *argv)
{
  printf("Setting the URL base path to: %s\n", URLParser::dos_path_to_url_path ("C:\\Cygwin\\////\\\\bin\\\\"));
  URLParser::SetBaseURL ("C:\\Cygwin\\////\\\\bin\\\\");

  URLParser rel_url_file ("file:pinco/panco");
  printf ("Parsing relative URL of type file:\n");
  printf ("Authority: %s\n", rel_url_file.GetHost ());
  printf ("Path: %s\n", rel_url_file.GetPath ());

  URLParser rel_url_cygfile ("cygfile:bin/passwd");
  printf ("Parsing relative URL of type cygfile:\n");
  printf ("Authority: %s\n", rel_url_cygfile.GetHost ());
  printf ("Path: %s\n", rel_url_cygfile.GetPath ());

  URLParser abs_url_file ("file:/usr/bin/passwd");
  printf ("Parsing absolute URL of type file:\n");
  printf ("Authority: %s\n", abs_url_file.GetHost ());
  printf ("Path: %s\n", abs_url_file.GetPath ());

  URLParser abs_url_cygfile ("cygfile:/usr/bin/passwd");
  printf ("Parsing absolute URL of type cygfile:\n");
  printf ("Authority: %s\n", abs_url_cygfile.GetHost ());
  printf ("Path: %s\n", abs_url_cygfile.GetPath ());
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: tt.exe
Type: application/octet-stream
Size: 665867 bytes
Desc: not available
Url : http://www.winehq.org/pipermail/wine-users/attachments/20011207/40d8f5fa/tt.obj


More information about the wine-users mailing list