Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert "Merge pull request #806 from eregon/fix-write_string" #861

Merged
merged 1 commit into from
Dec 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion ext/ffi_c/AbstractMemory.c
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,7 @@ memory_read_array_of_string(int argc, VALUE* argv, VALUE self)
* @raise {SecurityError} when writing unsafe string to memory
* @raise {IndexError} if +offset+ is too great
* @raise {NullPointerError} if memory not initialized
* Put a string in memory. Writes a final \0 byte.
* Put a string in memory.
*/
static VALUE
memory_put_string(VALUE self, VALUE offset, VALUE str)
Expand Down
28 changes: 7 additions & 21 deletions lib/ffi/pointer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,37 +85,23 @@ def read_string_to_null
# @param [String] str string to write
# @param [Numeric] len length of string to return
# @return [self]
# Write +len+ first bytes of +str+ in pointer's contents and a final \0 byte.
# Write +len+ first bytes of +str+ in pointer's contents.
#
# Same as:
# ptr.write_string(str, len) # with len not nil
def write_string_length(str, len)
write_string(str, len)
put_bytes(0, str, 0, len)
end unless method_defined?(:write_string_length)

# @param [String] str string to write
# @param [Numeric] len length of string to return
# @return [self]
# Write +str+ in pointer's contents.
# If +len+ is given, write the first +len+ bytes of +str+.
# In both cases a final \0 byte is written after the string.
# Write +str+ in pointer's contents, or first +len+ bytes if
# +len+ is not +nil+.
def write_string(str, len=nil)
if len
if len == size
warn "[DEPRECATION] Memory too small to write a final 0-byte in #{caller(1, 1)[0]}. This will raise an error in ffi-2.0. Please use write_bytes instead or enlarge the memory region."
write_bytes(str, 0, len)
else
put_char(len, 0) # Check size before writing str
write_bytes(str, 0, len)
end
else
if str.bytesize == size
warn "[DEPRECATION] Memory too small to write a final 0-byte in #{caller(1, 1)[0]}. This will raise an error in ffi-2.0. Please use write_bytes instead or enlarge the memory region."
write_bytes(str)
else
put_string(0, str)
end
end
len = str.bytesize unless len
# Write the string data without NUL termination
put_bytes(0, str, 0, len)
end unless method_defined?(:write_string)

# @param [Type] type type of data to read from pointer's contents
Expand Down
47 changes: 11 additions & 36 deletions spec/ffi/string_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,11 @@ module StrLibTest
describe "#write_string" do
# https://github.com/ffi/ffi/issues/805
describe "with no length given" do
it "writes a final \\0" do
it "writes no final \\0" do
ptr = FFI::MemoryPointer.new(8)
ptr.write_int64(-1)
ptr.write_string("äbc")
expect(ptr.read_bytes(5)).to eq("äbc\x00".b)
expect(ptr.read_string).to eq("äbc".b)
expect(ptr.read_bytes(5)).to eq("äbc\xff".b)
end

it "doesn't write anything when size is exceeded" do
Expand All @@ -119,22 +118,10 @@ module StrLibTest
expect(ptr.read_int64).to eq(-1)
end

if FFI::VERSION < "2"
it "prints a warning if final \\0 doesn't fit into memory" do
ptr = FFI::MemoryPointer.new(5)
expect do
ptr.write_string("äbcd")
end.to output(/memory too small/i).to_stderr
expect(ptr.read_string).to eq("äbcd".b)
end
else
it "denies writing if final \\0 doesn't fit into memory" do
ptr = FFI::MemoryPointer.new(5)
expect do
ptr.write_string("äbcd")
end.to raise_error(IndexError, /out of bounds/i)
expect(ptr.read_string).to eq("".b)
end
it "fits into memory" do
ptr = FFI::MemoryPointer.new(5)
ptr.write_string("äbcd")
expect(ptr.read_string).to eq("äbcd".b)
end
end

Expand All @@ -143,7 +130,7 @@ module StrLibTest
ptr = FFI::MemoryPointer.new(8)
ptr.write_int64(-1)
ptr.write_string("äbcd", 3)
expect(ptr.read_bytes(5)).to eq("äb\x00\xFF".b)
expect(ptr.read_bytes(5)).to eq("äb\xFF\xFF".b)
end

it "doesn't write anything when size is exceeded" do
Expand All @@ -155,22 +142,10 @@ module StrLibTest
expect(ptr.read_int64).to eq(-1)
end

if FFI::VERSION < "2"
it "prints a warning if final \\0 doesn't fit into memory" do
ptr = FFI::MemoryPointer.new(5)
expect do
ptr.write_string("äbcde", 5)
end.to output(/memory too small/i).to_stderr
expect(ptr.read_string).to eq("äbcd".b)
end
else
it "denies writing if final \\0 doesn't fit into memory" do
ptr = FFI::MemoryPointer.new(5)
expect do
ptr.write_string("äbcde", 5)
end.to raise_error(IndexError, /out of bounds/i)
expect(ptr.read_string).to eq("".b)
end
it "fits into memory" do
ptr = FFI::MemoryPointer.new(5)
ptr.write_string("äbcde", 5)
expect(ptr.read_string).to eq("äbcd".b)
end
end
end
Expand Down