Problem with binary numbers

P

perldude

A third-party module that I'm using has a couple of binary constants defined:

GENERIC_READ=10000000000000000000000000000000
GENERIC_EXECUTE=100000000000000000000000000000

The binary value for GENERIC_READ|GENERIC_EXECUTE would be:
10100000000000000000000000000000

I'm trying to check if a field in an object created by the module equals
GENERIC_READ|GENERIC_EXECUTE, but I'm running into a problem. If I print out
the value for a field that I know equals GENERIC_READ|GENERIC_EXECUTE, then it
prints out -1610612736.
But when I have the statement "print GENERIC_READ|GENERIC_EXECUTE", it prints
out 2684354560.

The following statements both print out 10100000000000000000000000000000:
printf("%0b\n", 2684354560);
printf("%0b\n", -1610612736);

So the binary representation for GENERIC_READ|GENERIC_EXECUTE has 2 different
decimal representations, a positive one and a negative one. Why does the
field in the object created by the third-party module have a negative decimal
representation, while my own code has a positive decimal representation?
 
T

Tad McClellan

A third-party module that I'm using has a couple of binary constants defined:

GENERIC_READ=10000000000000000000000000000000
GENERIC_EXECUTE=100000000000000000000000000000


That is not how you define constants in Perl.

Please show real Perl code.

The binary value for GENERIC_READ|GENERIC_EXECUTE would be:
10100000000000000000000000000000

I'm trying to check if a field in an object created by the module equals ^^^^^^^^^^
GENERIC_READ|GENERIC_EXECUTE,


Where is the Perl code for your attempts?

but I'm running into a problem.


If we cannot see the code, we cannot debug the code.

If I print out
the value


How do you print it out?

If we cannot see the code, we cannot debug the code.

for a field that I know equals GENERIC_READ|GENERIC_EXECUTE, then it
prints out -1610612736.


How do "know" that it is equal?

But when I have the statement "print GENERIC_READ|GENERIC_EXECUTE",


We finally get to some Real Perl Code. Thank you.

it prints
out 2684354560.


So the binary representation for GENERIC_READ|GENERIC_EXECUTE has 2 different
decimal representations, a positive one and a negative one. Why does the
field in the object created by the third-party module


You cannot really expect that we would be able to comment on the
internals of a module without even knowing the module's name, do you?

have a negative decimal
representation, while my own code has a positive decimal representation?


If you post a short and complete program *that we can run*, then
we will be able to explain it.

The program below makes output for me. If your code is doing
something different, then show that code and we will help
you fix it.

--------------------------------
#!/usr/bin/perl
use warnings;
use strict;

use constant GENERIC_READ => 0b10000000000000000000000000000000;
use constant GENERIC_EXECUTE => 0b100000000000000000000000000000;
my $ored = 0b10100000000000000000000000000000;
print "equal\n" if $ored == GENERIC_READ | GENERIC_EXECUTE;
 
A

Anno Siegel

A third-party module that I'm using has a couple of binary constants defined:

GENERIC_READ=10000000000000000000000000000000
GENERIC_EXECUTE=100000000000000000000000000000

The binary value for GENERIC_READ|GENERIC_EXECUTE would be:
10100000000000000000000000000000

I'm trying to check if a field in an object created by the module equals
GENERIC_READ|GENERIC_EXECUTE, but I'm running into a problem. If I print out
the value for a field that I know equals GENERIC_READ|GENERIC_EXECUTE, then it
prints out -1610612736.
But when I have the statement "print GENERIC_READ|GENERIC_EXECUTE", it prints
out 2684354560.

The following statements both print out 10100000000000000000000000000000:
printf("%0b\n", 2684354560);
printf("%0b\n", -1610612736);

So the binary representation for GENERIC_READ|GENERIC_EXECUTE has 2 different
decimal representations, a positive one and a negative one.

Put it the other way round: The bit pattern has two different numeric
interpretations -- one as an unsigned integer and one as a signed integer.
Perl integers contain a flag that says which interpretation is valid.
To see the difference:

use Devel::peek;
Dump 2684354560;
Dump -1610612736;
Why does the
field in the object created by the third-party module have a negative decimal
representation, while my own code has a positive decimal representation?

All you told us about the module is that it is "third party", so how can
you expect anyone to answer a question about it? It may be a bug in the
module or it may be deliberate, who knows.

If you use the numbers as masks to test against flags like GENERIC_READ
etc, the difference doesn't matter. If you must compare them for equality,
you can use sprintf( "%u", $x) == sprintf( "%u", $y).

Anno
 
P

perldude

Sorry I didn't include working code. The module I am using is Win32::perms,
which is available at http://www.roth.net/perl/perms/

Here is simplified code (running on my Windows 2000 machine with ActivePerl
5.8.3) which shows the problem:

#############################################
use Data::Dumper;
use Win32::perms;

@securityDescriptor;
$permsObject;

# dump the security descriptor for c:\winnt\system32 into the array
$permsObject = new Win32::perms("c:\\winnt\\system32");
$permsObject->Dump(\@securityDescriptor);
$permsObject->Close();

# remove all entries in the array that aren't "DACL". all the "DACL" entries
# are at the front of the array
$index = 0;
while ($securityDescriptor[$index]->{"Entry"} eq "DACL") {
$index++;
}
splice @securityDescriptor, $index;

# interate through the array and print out info about each ACE
$index = 1;
while ($index <= scalar(@securityDescriptor)) {
$aceRef = $securityDescriptor[$index-1];

print "-------------------------------------------------------\n";
print "ACE #$index:\n\n";

@decodedValues;
$decodedString;

Win32::perms::DecodeMask($aceRef, \@decodedValues);
$decodedString = Data::Dumper->Dump(\@decodedValues);
print "Win32::perms says that the ACE's Mask value is made up
of:\n$decodedString\n";

$gr_binary = sprintf("%0b", GENERIC_READ);
$ge_binary = sprintf("%0b", GENERIC_EXECUTE);
$gr_OR_ge = (GENERIC_READ|GENERIC_EXECUTE);
$gr_OR_ge_binary = sprintf("%0b", $gr_OR_ge);
print "GENERIC_READ in binary=$gr_binary\n";
print "GENERIC_EXECUTE in binary=$ge_binary\n";
print "GENERIC_READ|GENERIC_EXECUTE in binary=$gr_OR_ge_binary\n";
print "GENERIC_READ|GENERIC_EXECUTE in decimal=$gr_OR_ge\n";

$mask = $aceRef->{"Mask"};
$mask_binary = sprintf("%0b", $mask);
print "The ACE's Mask value in binary is: $mask_binary\n";
print "The ACE's Mask value in decimal is: $mask\n";

print "\n";

$index++;
}

###########################################

When I run that code, I get some output. Here is the output for the second
ACE, which is relevant since it's Mask value == GENERIC_READ|GENERIC_EXECUTE:

-------------------------------------------------------
ACE #2:

Win32::perms says that the ACE's Mask value is made up of:
$VAR1 = 'GENERIC_EXECUTE';
$VAR2 = 'GENERIC_READ';

GENERIC_READ in binary=10000000000000000000000000000000
GENERIC_EXECUTE in binary=100000000000000000000000000000
GENERIC_READ|GENERIC_EXECUTE in binary=10100000000000000000000000000000
GENERIC_READ|GENERIC_EXECUTE in decimal=2684354560
The ACE's Mask value in binary is: 10100000000000000000000000000000
The ACE's Mask value in decimal is: -1610612736

------------------------------------------------------

As you can see from the output, I know that the ACE's Mask value is
GENERIC_READ|GENERIC_EXECUTE because the call to Win32::perms::DecodeMask()
said so. When I print out the decimal value of the Mask value, it is a
negative number, but when I print out the decimal value of
GENERIC_READ|GENERIC_EXECUTE, it is a positive number.

While writing up this post, I realized that I can just use sprintf on those
two values to get their binary values and then compare them. But I'm still
curious as to why the decimal values are different. Thanks for your help.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,167
Messages
2,570,910
Members
47,453
Latest member
MadelinePh

Latest Threads

Top