[Win32utils-devel] win32-dir, unicode

Heesob Park phasis at gmail.com
Sun May 28 22:20:14 EDT 2006


Hi,

2006/5/28, Daniel Berger <djberg96 at gmail.com>:
> Heesob Park wrote:
> > Hi,
> >
> > 2006/5/28, Daniel Berger <djberg96 at gmail.com>:
> >> Heesob Park wrote:
> >>> Hi,
> > <snip>
> >> Thanks Heesob, but I'm getting some weird segfaults with wide character
> >> functions and buffers over 245 characters.  I posted about this to
> >> ruby-talk as well.  Here's some sample code that demonstrates the problem:
> >>
> >> require 'Win32API'
> >>
> >> GetFullPathNameW = Win32API.new('kernel32', 'GetFullPathNameW', 'PLPP', 'L')
> >>
> >> path = "C:\\test"
> >> buf  = 0.chr * 260 # 245 or less works ok
> >>
> >> if GetFullPathNameW.call(path, buf.size, buf, 0) == 0
> >>    puts "Failed"
> >>    exit
> >> end
> >>
> >> p buf.split("\0\0").first # BOOM!
> >>
> >> I'm not sure what the significance of 245 or less is.  I can inspect
> >> 'buf', copy and paste it to a separate editor as a string and run ops on
> >> it with no problem, so I'm very curious as to what's making Ruby segfault.
> >>
> > I'm very curious too.
> >
> > Your sample code don't segfault.
> > But I came across segfaults several times in modifing create_junction method.
> > It's behaviour is very unstable, as I insert p method,it sometimes runs OK.
> > It's location was mainly split method or get_last_error method.
> >
> > I guess it's not related with 245 or 260, but it seems to underlying C
> > pointer memory access failure problem.
> > Can you give me a sample stable segfault generating code?
>
> To add even more mystery to this problem, that code isn't segfaulting
> for me at the moment, though it was regularly last night (I still have
> the console window open that shows the segfaults to prove it to myself).
>
> I saw the same behavior you mentioned - inserting a 'puts' would
> sometimes cause code that was previously segfaulting to suddenly work.
>
> Well, let's put the Unicode stuff on hold for now.  Perhaps deep
> inspection of string.c some day will reveal what the potential problem is.
>
I have found out what is the problem.
It's not bug of Ruby or Windows, it is only bug of code.

First try this:

require 'Win32API'
GetFullPathNameW = Win32API.new('kernel32','GetFullPathNameW','PLPP', 'L')
for i in 1..100
path = "c:\\test"
buf  = 0.chr * 260
if GetFullPathNameW.call(path, buf.size, buf, 0) == 0
    puts "Failed"
end
p buf.split("\0\0").first
end

It will cause various errors like
uninitialized constant GetFullPathNameW (NameError)
or
segfault.

Next, try this:

require 'Win32API'
GetFullPathNameW = Win32API.new('kernel32','GetFullPathNameW','PLPP', 'L')
for i in 1..100
path = "c:\\test"
buf  = 0.chr * 260
# buf.size/2 -> actual length of buf
if GetFullPathNameW.call(path, buf.size/2, buf, 0) == 0
    puts "Failed"
end
p buf.split("\0\0").first
end

It runs Ok. but the result is not correct.

Next , try this:

require 'Win32API'
GetFullPathNameW = Win32API.new('kernel32','GetFullPathNameW','PLPP', 'L')
for i in 1..100
# append \0 to path
path = "c:\\test\0"
buf  = 0.chr * 260
# buf.size/2 -> actual length of buf in unicode string
if GetFullPathNameW.call(path, buf.size/2, buf, 0) == 0
    puts "Failed"
end
p buf.split("\0\0").first
end

It runs ok. The result is correct.

Finally, the complete and correct code is like this:

require 'Win32API'
GetFullPathNameW = Win32API.new('kernel32','GetFullPathNameW','PLPP', 'L')
for i in 1..100
path = "c\0:\0\\\0t\0e\0s\0t\0\0"
buf  = 0.chr * 260
# buf.size/2 -> actual length of buf in unicode string
if GetFullPathNameW.call(path, buf.size/2, buf, 0) == 0
    puts "Failed"
end
buf = buf.split("\0\0").first
buf = (buf.size % 2).zero? ? buf : buf+"\0"
p buf
end

Remeber, Ruby's string is terminated with "\0" implicitly, but UTF16
string requires double "\0".
For ascii chars, it happens trailing three "\0"  : one for ascii char
and two for string termination.

Regards,

Park Heesob



More information about the win32utils-devel mailing list