integer overflow in awk

Hello,

I'm using awk to convert dotted quad ip numbers to unsigned integers (10.3.4). At least I thought I was! Anything over 126.255.255.255 is returned as 0x7FFFFFFF (2147483647).

Here's the command:

echo 127.255.255.255 | \
awk -F. '{printf("%u\n", $1256*256256 + $2256256 + $3*256 + $4)}'

GNU awk doesn't share this problem. Should I just go compile gawk?

--
Cole

15 PB, Mac OS X (10.3.4)

Posted on Jun 8, 2006 12:57 PM

Reply
11 replies

Jun 8, 2006 4:21 PM in response to Cole Tierney

Hi Cole,
I don't have a complete answer as I'm unfamiliar with the source code of the BSD awk but I can characterize the issue. Apparently numbers in awk a C ints. In binary, these are 32 bit numbers. That is the same data structure used for IP addresses although that isn't clear from the "dot notation". Thus in theory, the data structure should be large enough to handle all standard IP addresses. However, I would guess that ints in the BSD awk are compiled as signed integers. Thus, ints are used to represent numbers between -2147483648 and 2147483647, I assume represented in "two's compliment". That means that half of the numbers available are used to represent negative numbers so only about half of the possible network addresses can be represented as decimal numbers in BSD's awk.

On the other hand, integers in GNU's awk must be C longs, or at least can be. As a consequence, you would have to multiply two IP addresses together before bumping against the corresponding limitations. Therefore I strongly recommend that you compile GNU's awk and install it. However, that would have been my answer even if you hadn't specified an issue. Even when emulating awk, GNU's awk is far more capable than that of BSD. When run as gawk, GNU's awk sports a feature set beside which BSD's awk pales by comparison!
--
Gary
~~~~
I always say beauty is only sin deep.
-- Saki, "Reginald's Choir Treat"

Jun 8, 2006 5:24 PM in response to Cole Tierney

Hi Cole,
No, that's not the traditional method for using your own software in place of system utilities. The biggest problem with replacing system software is that it can break other other software or scripts, particularly Apple's own, that depend on the original version.

The recommended procedure is to put the new software in another location, traditionally /usr/local, and putting directories containing the executables, /usr/local/bin and /usr/local/sbin, in your personal path ahead of the system directories. That way you will enjoy the benefits of your upgrade while developers still have access to the original.

Neither will you have to link awk to gawk because installation of the GNU version will do that for you, putting both in the same directory. (by default /usr/local/bin) When invoked as awk, gawk will faithfully emulate awk.

As an aside, Fink will install gawk for you.
--
Gary
~~~~
Cynic, n.:
Experienced.

Jun 8, 2006 7:37 PM in response to Cole Tierney

It's not awk.

It's crude, but it in the tests that I tried here worked
pretty well.

Andy


cc -o ipDotted2Hex ipDotted2Hex.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>

#define USAGE "%s <dotted quad ip address>\n"

int main(int argc, char *argv[]) {

struct in_addr ipaddress;

if (argc < 2) {
fprintf(stderr, USAGE, argv[0]);
exit(1);
}

/* seems odd, but the man page say '0' is a failure. */
if (inet_aton(argv[1], &ipaddress) == 0) {
perror("inet_aton: ");
exit(errno);
}

printf("%x\n", ipaddress.s_addr);

return 0;
}

Jun 9, 2006 11:13 AM in response to Gary Kerbaugh

Hi Gary,
The recommended procedure is to put the new software in another
location, traditionally /usr/local, and putting directories containing
the executables, /usr/local/bin and /usr/local/sbin, in your personal
path ahead of the system directories.


I decided to complile gawk as well as Nils' program. I've reordered my path so that my shell finds gawk first.

Is there a similar technique to override awk's man page with gawk's version?

--
Cole

Jun 9, 2006 1:57 PM in response to Cole Tierney

Hi Cole,
Yes, of course. In fact the method is almost identical. It's called a MANPATH and it serves essentially the same function as the path. Just put /usr/local/man and /usr/local/share/man ahead of system paths in your MANPATH.

However, there is a catch. Unlike the shell, the BSD man utility can function without a MANPATH. I believe that it looks at your PATH variable and infers where the corresponding man files would be located. You can see what it uses by executing "manpath". Despite what many people have flatly stated around here, (without stating a reason) I've never heard a compelling reason for not setting your own MANPATH as long as you do a good job of it. I assume that because the man utility can do a pretty fair job on its own, these people are saying that most people can't do better so they don't recommend trying. I can do better and I do, so I know that there's nothing inherently wrong with doing it yourself.

Before trying it yourself, it would be a good idea to test to see what kind of job the man utility does on its own. Now that you've added /usr/local/bin to your path, execute the following in your shell:

manpath

If /usr/local/share/man appears before the system man directories, then there's nothing for you to do. Otherwise you could use something like:

export MANPATH=/usr/local/share/man:/usr/local/man:`manpath`

and your MANPATH should be better than what the system would do for you.
--
Gary
~~~~
The wonderful thing about a dancing bear is not
how well he dances, but that he dances at all.

This thread has been closed by the system or the community team. You may vote for any posts you find helpful, or search the Community for additional answers.

integer overflow in awk

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple Account.