[WS2_32] Import inet_addr from wine

The old implementation was buggy and caused stack corruption (triggered by ws2_32_winetest:sock test_inet_pton)
This commit is contained in:
Timo Kreuzer
2026-07-01 06:52:45 +00:00
parent e848ce1c52
commit 6679825f21
3 changed files with 88 additions and 89 deletions
+1
View File
@@ -42,6 +42,7 @@ list(APPEND SOURCE
src/spinstal.c
src/sputil.c
src/startup.c
src/wine.c
src/wsautil.c
inc/ws2_32.h)
-89
View File
@@ -63,95 +63,6 @@
/* FUNCTIONS *****************************************************************/
/*
* @implemented
*/
ULONG
WSAAPI
inet_addr(IN CONST CHAR FAR* cp)
{
register u_long val, base, n;
register unsigned char c;
u_long parts[4], *pp = parts;
if (!cp) return INADDR_ANY;
if (!isdigit(*cp)) return INADDR_NONE;
again:
/*
* Collect number up to ``.''.
* Values are specified as for C:
* 0x=hex, 0=octal, other=decimal.
*/
val = 0; base = 10;
if (*cp == '0') {
if (*++cp == 'x' || *cp == 'X')
base = 16, cp++;
else
base = 8;
}
while ((c = *cp)) {
if (isdigit(c)) {
val = (val * base) + (c - '0');
cp++;
continue;
}
if (base == 16 && isxdigit(c)) {
val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A'));
cp++;
continue;
}
break;
}
if (*cp == '.') {
/*
* Internet format:
* a.b.c.d
* a.b.c (with c treated as 16-bits)
* a.b (with b treated as 24 bits)
*/
if (pp >= parts + 4) return (INADDR_NONE);
*pp++ = val;
cp++;
goto again;
}
/*
* Check for trailing characters.
*/
if (*cp && !isspace((UCHAR)*cp)) return (INADDR_NONE);
*pp++ = val;
/*
* Concoct the address according to
* the number of parts specified.
*/
n = (u_long)(pp - parts);
switch (n) {
case 1: /* a -- 32 bits */
val = parts[0];
break;
case 2: /* a.b -- 8.24 bits */
val = (parts[0] << 24) | (parts[1] & 0xffffff);
break;
case 3: /* a.b.c -- 8.8.16 bits */
val = (parts[0] << 24) | ((parts[1] & 0xff) << 16) |
(parts[2] & 0xffff);
break;
case 4: /* a.b.c.d -- 8.8.8.8 bits */
val = (parts[0] << 24) | ((parts[1] & 0xff) << 16) |
((parts[2] & 0xff) << 8) | (parts[3] & 0xff);
break;
default:
return (INADDR_NONE);
}
val = htonl(val);
return (val);
}
/*
* @implemented
*/
+87
View File
@@ -0,0 +1,87 @@
/*
* Protocol-level socket functions
*
* Copyright (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
* Copyright (C) 2001 Stefan Leichter
* Copyright (C) 2004 Hans Leidekker
* Copyright (C) 2005 Marcus Meissner
* Copyright (C) 2006-2008 Kai Blin
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <ws2_32.h>
#define NDEBUG
#include <debug.h>
#define TRACE(...)
/***********************************************************************
* inet_addr (ws2_32.11)
*/
u_long WINAPI inet_addr( const char *str )
{
unsigned long a[4] = { 0 };
const char *s = str;
unsigned char *d;
unsigned int i;
u_long addr;
char *z;
TRACE( "str %s.\n", debugstr_a(str) );
if (!s)
{
SetLastError( WSAEFAULT );
return INADDR_NONE;
}
d = (unsigned char *)&addr;
if (s[0] == ' ' && !s[1]) return 0;
for (i = 0; i < 4; ++i)
{
a[i] = strtoul( s, &z, 0 );
if (z == s || !isdigit( *s )) return INADDR_NONE;
if (!*z || isspace(*z)) break;
if (*z != '.') return INADDR_NONE;
s = z + 1;
}
if (i == 4) return INADDR_NONE;
switch (i)
{
case 0:
a[1] = a[0] & 0xffffff;
a[0] >>= 24;
/* fallthrough */
case 1:
a[2] = a[1] & 0xffff;
a[1] >>= 16;
/* fallthrough */
case 2:
a[3] = a[2] & 0xff;
a[2] >>= 8;
}
for (i = 0; i < 4; ++i)
{
if (a[i] > 255) return INADDR_NONE;
d[i] = a[i];
}
return addr;
}