Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

/*
# Modified by OpenC3, Inc.
# All changes Copyright 2022, OpenC3, Inc.
# All changes Copyright 2026, OpenC3, Inc.
# All Rights Reserved
#
# This file may also be used under the terms of a commercial license
Expand Down Expand Up @@ -47,9 +47,18 @@ static VALUE polynomial_conversion_call(VALUE self, VALUE value, VALUE myself, V
int index = 0;
double converted = 0.0;
double raised_to_power = 1.0;
volatile VALUE coeffs = rb_ivar_get(self, id_ivar_coeffs);
long coeffs_length = RARRAY_LEN(coeffs);
double double_value = RFLOAT_VALUE(rb_funcall(value, id_method_to_f, 0));
volatile VALUE coeffs;
long coeffs_length;
double double_value;

/* Return nil if value is nil (item outside buffer bounds) */
if (NIL_P(value)) {
return Qnil;
}

coeffs = rb_ivar_get(self, id_ivar_coeffs);
coeffs_length = RARRAY_LEN(coeffs);
double_value = RFLOAT_VALUE(rb_funcall(value, id_method_to_f, 0));

/* Handle C0 */
double coeff = RFLOAT_VALUE(rb_ary_entry(coeffs, 0));
Expand Down
5 changes: 3 additions & 2 deletions openc3/ext/openc3/ext/structure/structure.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

/*
# Modified by OpenC3, Inc.
# All changes Copyright 2024, OpenC3, Inc.
# All changes Copyright 2026, OpenC3, Inc.
# All Rights Reserved
#
# This file may also be used under the terms of a commercial license
Expand Down Expand Up @@ -520,7 +520,8 @@ static VALUE binary_accessor_read(VALUE self, VALUE param_bit_offset, VALUE para

if (!check_bounds_and_buffer_size(bit_offset, bit_size, (int)buffer_length, param_endianness, param_data_type, &lower_bound, &upper_bound))
{
rb_funcall(self, id_method_raise_buffer_error, 5, symbol_read, param_buffer, param_data_type, param_bit_offset, param_bit_size);
/* Return nil for out-of-bounds reads (supports undersized packets with ALLOW_SHORT) */
return Qnil;
}

if ((param_data_type == symbol_STRING) || (param_data_type == symbol_BLOCK))
Expand Down
2 changes: 1 addition & 1 deletion openc3/lib/openc3/accessors/accessor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def enforce_length

# This sets the short_buffer_allowed flag in the Packet class
# which allows packets that have a buffer shorter than the defined size.
# Note that the buffer is still resized to the defined length
# Items outside the buffer bounds will return nil when read.
def enforce_short_buffer_allowed
return false
end
Expand Down
10 changes: 7 additions & 3 deletions openc3/lib/openc3/accessors/binary_accessor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
# GNU Affero General Public License for more details.

# Modified by OpenC3, Inc.
# All changes Copyright 2024, OpenC3, Inc.
# All changes Copyright 2026, OpenC3, Inc.
# All Rights Reserved
#
# This file may also be used under the terms of a commercial license
Expand Down Expand Up @@ -339,7 +339,8 @@ def self.read(bit_offset, bit_size, data_type, buffer, endianness)
end

result, lower_bound, upper_bound = check_bounds_and_buffer_size(bit_offset, bit_size, buffer.length, endianness, data_type)
raise_buffer_error(:read, buffer, data_type, given_bit_offset, given_bit_size) unless result
# Return nil for out-of-bounds reads (supports undersized packets with ALLOW_SHORT)
return nil unless result

if (data_type == :STRING) || (data_type == :BLOCK)
#######################################
Expand Down Expand Up @@ -936,6 +937,9 @@ def self.read_array(bit_offset, bit_size, data_type, array_size, buffer, endiann
lower_bound = bit_offset / 8
upper_bound = (bit_offset + array_size - 1) / 8

# Return nil for out-of-bounds reads (supports undersized packets with ALLOW_SHORT)
return nil if upper_bound >= buffer.length

# Check for byte alignment
byte_aligned = ((bit_offset % 8) == 0)

Expand Down Expand Up @@ -1420,7 +1424,7 @@ def enforce_length

# This sets the short_buffer_allowed flag in the Packet class
# which allows packets that have a buffer shorter than the defined size.
# Note that the buffer is still resized to the defined length
# Items outside the buffer bounds will return nil when read.
def enforce_short_buffer_allowed
return false
end
Expand Down
2 changes: 1 addition & 1 deletion openc3/lib/openc3/accessors/form_accessor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def enforce_length

# This sets the short_buffer_allowed flag in the Packet class
# which allows packets that have a buffer shorter than the defined size.
# Note that the buffer is still resized to the defined length
# Items outside the buffer bounds will return nil when read.
def enforce_short_buffer_allowed
return true
end
Expand Down
2 changes: 1 addition & 1 deletion openc3/lib/openc3/accessors/http_accessor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ def enforce_length

# This sets the short_buffer_allowed flag in the Packet class
# which allows packets that have a buffer shorter than the defined size.
# Note that the buffer is still resized to the defined length
# Items outside the buffer bounds will return nil when read.
def enforce_short_buffer_allowed
return @body_accessor.enforce_short_buffer_allowed
end
Expand Down
2 changes: 1 addition & 1 deletion openc3/lib/openc3/accessors/json_accessor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ def enforce_length

# This sets the short_buffer_allowed flag in the Packet class
# which allows packets that have a buffer shorter than the defined size.
# Note that the buffer is still resized to the defined length
# Items outside the buffer bounds will return nil when read.
def enforce_short_buffer_allowed
return true
end
Expand Down
2 changes: 1 addition & 1 deletion openc3/lib/openc3/accessors/template_accessor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ def enforce_length

# This sets the short_buffer_allowed flag in the Packet class
# which allows packets that have a buffer shorter than the defined size.
# Note that the buffer is still resized to the defined length
# Items outside the buffer bounds will return nil when read.
def enforce_short_buffer_allowed
return true
end
Expand Down
2 changes: 1 addition & 1 deletion openc3/lib/openc3/accessors/xml_accessor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ def enforce_length

# This sets the short_buffer_allowed flag in the Packet class
# which allows packets that have a buffer shorter than the defined size.
# Note that the buffer is still resized to the defined length
# Items outside the buffer bounds will return nil when read.
def enforce_short_buffer_allowed
return true
end
Expand Down
5 changes: 4 additions & 1 deletion openc3/lib/openc3/conversions/polynomial_conversion.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
# GNU Affero General Public License for more details.

# Modified by OpenC3, Inc.
# All changes Copyright 2024, OpenC3, Inc.
# All changes Copyright 2026, OpenC3, Inc.
# All Rights Reserved
#
# This file may also be used under the terms of a commercial license
Expand Down Expand Up @@ -45,6 +45,9 @@ def initialize(*coeffs)
# @param (see Conversion#call)
# @return [Float] The value with the polynomial applied
def call(value, myself, buffer)
# Return nil if value is nil (item outside buffer bounds)
return nil if value.nil?

value = value.to_f

# Handle C0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
# GNU Affero General Public License for more details.

# Modified by OpenC3, Inc.
# All changes Copyright 2024, OpenC3, Inc.
# All changes Copyright 2026, OpenC3, Inc.
# All Rights Reserved
#
# This file may also be used under the terms of a commercial license
Expand Down Expand Up @@ -116,6 +116,9 @@ def add_segment(lower_bound, *coeffs)
# @param (see Conversion#call)
# @return [Float] The value with the polynomial applied
def call(value, packet, buffer)
# Return nil if value is nil (item outside buffer bounds)
return nil if value.nil?

# Try to find correct segment
@segments.each do |segment|
return segment.calculate(value) if value >= segment.lower_bound
Expand Down
6 changes: 6 additions & 0 deletions openc3/lib/openc3/packets/packet.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1049,6 +1049,9 @@ def check_limits(limits_set = :DEFAULT, ignore_persistence = false)
if item.limits.enabled
value = read_item(item)

# Skip limits checking if value is nil (item outside buffer bounds)
next if value.nil?

# Handle state monitoring and value monitoring differently
if item.states
handle_limits_states(item, value)
Expand Down Expand Up @@ -1526,6 +1529,9 @@ def handle_limits_values(item, value, limits_set, ignore_persistence)
end

def apply_format_string_and_units(item, value, value_type)
# Return nil as-is - can't format a value that doesn't exist
return nil if value.nil?

if value_type == :FORMATTED or value_type == :WITH_UNITS
if item.format_string && value
value = sprintf(item.format_string, value)
Expand Down
4 changes: 2 additions & 2 deletions openc3/lib/openc3/packets/packet_config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -493,8 +493,8 @@ def process_current_packet(parser, keyword, params)
'APPEND_ARRAY_ITEM', 'APPEND_ARRAY_PARAMETER', 'STRUCTURE', 'APPEND_STRUCTURE'
start_item(parser)

# Allow this packet to be received with less data than the defined length
# without generating a warning.
# Allow this packet to be received with less data than the defined length.
# Items that are beyond the buffer will return nil when read.
when 'ALLOW_SHORT'
@current_packet.short_buffer_allowed = true

Expand Down
10 changes: 7 additions & 3 deletions openc3/lib/openc3/packets/structure.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
# GNU Affero General Public License for more details.

# Modified by OpenC3, Inc.
# All changes Copyright 2024, OpenC3, Inc.
# All changes Copyright 2026, OpenC3, Inc.
# All Rights Reserved
#
# This file may also be used under the terms of a commercial license
Expand Down Expand Up @@ -680,8 +680,12 @@ def internal_buffer_equals(buffer)
if @accessor.enforce_length
if @buffer.length != @defined_length
if @buffer.length < @defined_length
resize_buffer()
raise "Buffer length less than defined length" unless @short_buffer_allowed
# Only resize if short_buffer_allowed is false
# When short_buffer_allowed is true, keep the buffer short so reads
# of items beyond the buffer return nil
unless @short_buffer_allowed
raise "Buffer length less than defined length"
end
elsif @fixed_size and @defined_length != 0
raise "Buffer length greater than defined length"
end
Expand Down
25 changes: 14 additions & 11 deletions openc3/python/openc3/accessors/binary_accessor.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2025 OpenC3, Inc.
# Copyright 2026 OpenC3, Inc.
# All Rights Reserved.
#
# This program is free software; you can modify and/or redistribute it
Expand Down Expand Up @@ -105,7 +105,9 @@ def raise_buffer_error(cls, read_write, buffer, data_type, given_bit_offset, giv
def handle_read_variable_bit_size(self, item, _buffer):
length_value = self.packet.read(item.variable_bit_size["length_item_name"], "CONVERTED")
if item.array_size is not None:
item.array_size = (length_value * item.variable_bit_size["length_bits_per_count"]) + item.variable_bit_size["length_value_bit_offset"]
item.array_size = (length_value * item.variable_bit_size["length_bits_per_count"]) + item.variable_bit_size[
"length_value_bit_offset"
]
else:
if item.data_type == "INT" or item.data_type == "UINT":
# QUIC encoding is currently assumed for individual variable sized integers
Expand Down Expand Up @@ -133,7 +135,7 @@ def read_item(self, item, buffer):
# Structure is used to read items with parent, not accessor
structure_buffer = self.read_item(item.parent_item, buffer)
structure = item.parent_item.structure
return structure.read(item.key, 'RAW', structure_buffer)
return structure.read(item.key, "RAW", structure_buffer)
else:
if item.variable_bit_size:
self.handle_read_variable_bit_size(item, buffer)
Expand Down Expand Up @@ -291,7 +293,7 @@ def write_item(self, item, value, buffer):
# Structure is used to write items with parent, not accessor
structure_buffer = self.read_item(item.parent_item, buffer)
structure = item.parent_item.structure
structure.write(item.key, value, 'RAW', structure_buffer)
structure.write(item.key, value, "RAW", structure_buffer)
if item.parent_item.variable_bit_size:
self.handle_write_variable_bit_size(item.parent_item, structure_buffer, buffer)
BinaryAccessor.class_write_item(item.parent_item, structure_buffer, buffer)
Expand Down Expand Up @@ -355,8 +357,9 @@ def read(cls, bit_offset, bit_size, data_type, buffer, endianness):
result, lower_bound, upper_bound = cls.check_bounds_and_buffer_size(
bit_offset, bit_size, len(buffer), endianness, data_type
)
# Return None for out-of-bounds reads (supports undersized packets with ALLOW_SHORT)
if not result:
cls.raise_buffer_error("read", buffer, data_type, given_bit_offset, given_bit_size)
return None

if data_type in ["STRING", "BLOCK"]:
#######################################
Expand Down Expand Up @@ -871,6 +874,10 @@ def read_array(cls, bit_offset, bit_size, data_type, array_size, buffer, endiann
lower_bound = math.floor(bit_offset / 8)
upper_bound = math.floor((bit_offset + array_size - 1) / 8)

# Return None for out-of-bounds reads (supports undersized packets with ALLOW_SHORT)
if upper_bound >= len(buffer):
return None

# Check for byte alignment
byte_aligned = (bit_offset % 8) == 0

Expand Down Expand Up @@ -936,9 +943,7 @@ def read_array(cls, bit_offset, bit_size, data_type, array_size, buffer, endiann
)
)
else:
raise ValueError(
f"bit_size is {given_bit_size} but must be 32 or 64 for data_type {data_type}"
)
raise ValueError(f"bit_size is {given_bit_size} but must be 32 or 64 for data_type {data_type}")

else:
raise ValueError(f"bit_offset {given_bit_offset} is not byte aligned for data_type {data_type}")
Expand Down Expand Up @@ -1149,9 +1154,7 @@ def write_array(
*values,
)
else:
raise ValueError(
f"bit_size is {given_bit_size} but must be 32 or 64 for data_type {data_type}"
)
raise ValueError(f"bit_size is {given_bit_size} but must be 32 or 64 for data_type {data_type}")
else:
raise ValueError(f"bit_offset {given_bit_offset} is not byte aligned for data_type {data_type}")

Expand Down
2 changes: 1 addition & 1 deletion openc3/python/openc3/accessors/form_accessor.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def enforce_length(self):

# This sets the short_buffer_allowed flag in the Packet class
# which allows packets that have a buffer shorter than the defined size.
# Note that the buffer is still resized to the defined length
# Items outside the buffer bounds will return None when read.
def enforce_short_buffer_allowed(self):
return True

Expand Down
2 changes: 1 addition & 1 deletion openc3/python/openc3/accessors/http_accessor.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ def enforce_length(self):

# This sets the short_buffer_allowed flag in the Packet class
# which allows packets that have a buffer shorter than the defined size.
# Note that the buffer is still resized to the defined length
# Items outside the buffer bounds will return None when read.
def enforce_short_buffer_allowed(self):
return self.body_accessor.enforce_short_buffer_allowed()

Expand Down
2 changes: 1 addition & 1 deletion openc3/python/openc3/accessors/template_accessor.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ def enforce_length(self):

# This sets the short_buffer_allowed flag in the Packet class
# which allows packets that have a buffer shorter than the defined size.
# Note that the buffer is still resized to the defined length
# Items outside the buffer bounds will return None when read.
def enforce_short_buffer_allowed(self):
return True

Expand Down
6 changes: 5 additions & 1 deletion openc3/python/openc3/conversions/polynomial_conversion.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2024 OpenC3, Inc.
# Copyright 2026 OpenC3, Inc.
# All Rights Reserved.
#
# This program is free software; you can modify and/or redistribute it
Expand Down Expand Up @@ -34,6 +34,10 @@ def __init__(self, *coeffs):
# @param (see Conversion#call)
# @return [Float] The value with the polynomial applied
def call(self, value, myself, buffer):
# Return None if value is None (item outside buffer bounds)
if value is None:
return None

value = float(value)

# Handle C0
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2023 OpenC3, Inc.
# Copyright 2026 OpenC3, Inc.
# All Rights Reserved.
#
# This program is free software; you can modify and/or redistribute it
Expand Down Expand Up @@ -92,6 +92,10 @@ def add_segment(self, lower_bound, *coeffs):
# @param (see Conversion#call)
# @return [Float] The value with the polynomial applied
def call(self, value, packet, buffer):
# Return None if value is None (item outside buffer bounds)
if value is None:
return None

# Try to find correct segment
for segment in self.segments:
if value >= segment.lower_bound:
Expand Down
Loading
Loading