FOUND IT!

Correct behaviour relies on a long overflowing, which it does on 32 bit
machines, but not on 64 bit machines.

From onepage(...) in move.c:

long n;
...
while (n <= curwin->w_height && loff.lnum >= 1)
{
topline_back(&loff);
n += loff.height;
}
if (n <= curwin->w_height) /* at begin of file */
...

From topline_back(...) in move.c:

if (lp->lnum < 1)
lp->height = MAXCOL;

From vim.h:

#if SIZEOF_INT >= 4
# ifdef __MVS__
# define MAXCOL (0x3fffffffL) /* maximum column number, 30 bits */
# else
# define MAXCOL (0x7fffffffL) /* maximum column number, 31 bits */
# endif
#else

In the usual, non __MVS__ case, on 32 or 64 bit machines, we have
MAXCOL=0x7fffffffL. On at least most 32 bit machines,
sizeof(int)==sizeof(long), so n overflows and becomes negative at
n += loff.height when we reach top-of-file, and the if is entered. On at
least some 64 bit machines, sizeof(int)<sizeof(long) (4 vs. 8, it
seems), and so n does not overflow but just gets huge.

The code is clearly wrong, but I'm not 100% sure what the intentions
are.

Perhaps the if should be

if (loff.lnum < 1) /* at begin of file */

?

I don't have time right now to try it, and my build environment isn't
quite set up right yet and not worth the trouble to do so as I'm
thinking of doing an OS reinstallation in a day or two. Can someone else
review the change / test it / suggest something else if it's wrong?

I don't have a 64bit machine to try it on, but wouldn't it be simpler
just to change the declaration of n from long to int?

I thought of that, but suspect it would mess up 16 bit machines. Not
sure if anyone cares about that anymore.

It also wouldn't fix the __MVS__ case which will suffer from the same
problem for a different reason.

And to cross all the ts, the behaviour of overflow with signed integers
is undefined in the C language. But while it can be described as a dodgy
piece of code, for most hardware platforms there shouldn't be a problem.
I doubt this is the only place relying on undefined language behaviour.

I doubt it too. But surely it would be better to have a more sane test
than relying on platform-specific ill-defined oddities.

To really be picky, probably MAXCOL is not a good choice of value for
height in the 'above first line' case. Something like LONG_MAX (does
that macro exist?--and on which platforms?) would be more appropriate.
It would return us to relying on the overflow, though, which IMHO isn't
really the best solution.

Bram probably will have a preferred way of fixing this, I suppose. Now
the problem has been pinpointed it should be pretty trivial for him to
decide on a fix. Probably more helpful for him if someone can test a
proposed fix, though.

Ben.




--
You received this message from the "vim_dev" maillist.
For more information, visit http://www.vim.org/maillist.php

Raspunde prin e-mail lui