At 05:51 PM 7/24/00 -0400, Jordan Henderson wrote:
>If I may speak for Craig, I think he was suggesting that there be a
>counter set before the loop and incremented in the loop to see if this
>loop has been executed some unreasonable number of times and aborting
>when this is detected.
Yes, that was the idea. It wouldn't create a workable situation out of an
unworkable one, but it would be better to get an unexplained abort than
to loop forever in kernel mode, allocating another chunk of memory at each
iteration.
>But, that doesn't seem to be a good suggestion. As we can see from
>inspection and from the attached debugging that Anders Wallin performed,
>the rlen/rsiz are never changed in the loop. This loop is clearly bogus,
>so why bother counting the number of times it will loop invalidly? As
>it stands, this code will always loop infinitely when (rlen < rsiz) is
>true on entry (or abort from an eventual getjpi() status error).
>
>This loop should be avoided, not aborted! Now, granted, there may be
>a case that's being missed here (when all the identifiers weren't
>gotten in the first pass), but this loop is no solution.
Jordan, welcome to the club of those who have read the code incorrectly.
The loop only appears to have no exit strategy, and indeed when looking only
at the loop by itself it's hard to see how rlen or rsz could ever change
within it:
while (rlen < rsz) {
/* We didn't get all the identifiers on the first pass. Allocate a
* buffer much larger than $GETJPI wants (rsz is size in bytes that
* were needed to hold all identifiers at time of last call; we'll
* allocate that many unsigned long ints), and go back and get 'em.
*/
if (jpilist[1].bufadr != rlst) Safefree(jpilist[1].bufadr);
jpilist[1].bufadr = New(1320,mask,rsz,unsigned long int);
jpilist[1].buflen = rsz * sizeof(unsigned long int);
_ckvmssts(sys$getjpiw(0,NULL,NULL,&jpilist[1],iosb,NULL,NULL));
_ckvmssts(iosb[0]);
}
I made the same mistake when I first looked at this, as did the original
author of the code when he suggested the fix I repeated. However, due to
the dark magic of item lists, the $getjpiw call will fill in rsz, supposedly
with the size in bytes of what it really wants to give you (but perhaps
didn't have room for), and it should fill in rlen with the amount of stuff
it *did* actually give you. This entire structure is passed to $getjpiw:
struct itmlst_3 jpilist[4] = { {sizeof iprv, JPI$_IMAGPRIV, iprv, &dummy},
{sizeof rlst, JPI$_RIGHTSLIST, rlst, &rlen},
{ sizeof rsz, JPI$_RIGHTS_SIZE, &rsz, &dummy},
{ 0, 0, 0, 0} };
In Anders's case, it's saying "I want to give you 184 bytes, but I'm only
giving you 40 bytes because that's all I have room for." This is bogus
because the default buffer size is 512. So, the best theory I have is that
$getjpiw is returning a rightslist smaller than the size it knows it should
need, and it may be doing this because there are no system identifiers, if
indeed this is the same problem someone noticed a couple of years ago.
Possibly some other corruption of the rights database could cause the
problem, and the real solution is to fix the system. However, we should
protect Perl from this if we can come up with a reliable, low-cost way of
doing so. This might be one way to do that, though I can't test it.
Anders, if you are still wth us, would it be possible to take it for a spin?
--- vms/vms.c;-0 Tue Jul 11 15:40:25 2000
+++ vms/vms.c Mon Jul 24 18:05:15 2000
@@ -2906,6 +2906,11 @@
jpilist[1].buflen = rsz * sizeof(unsigned long int);
_ckvmssts(sys$getjpiw(0,NULL,NULL,&jpilist[1],iosb,NULL,NULL));
_ckvmssts(iosb[0]);
+ /* If it gave us less than it wanted to despite ample buffer space, it's
+ broken. Is your system missing a system identifier? */
+ if (rlen < rsz && rsz <= sizeof(jpilist[1].buflen)) {
+ Perl_croak(aTHX_ "Error getting rights in vms_image_init: check your rights
+database.");
+ }
}
mask = jpilist[1].bufadr;
/* Check attribute flags for each identifier (2nd longword); protected
[end of possible kernel-mode endless loop avoidance patch]
_______________________________________________
Craig A. Berry
mailto:[EMAIL PROTECTED]