Add a limit on the number of points in a GPS trace

This commit is contained in:
Tom Hughes 2024-02-24 14:34:09 +00:00
parent 4c029873bb
commit 741ed58838
4 changed files with 24 additions and 2 deletions

View file

@ -202,7 +202,7 @@ class Trace < ApplicationRecord
logger.info("GPX Import importing #{name} (#{id}) from #{user.email}") logger.info("GPX Import importing #{name} (#{id}) from #{user.email}")
file.open do |file| file.open do |file|
gpx = GPX::File.new(file.path) gpx = GPX::File.new(file.path, :maximum_points => Settings.max_trace_size)
f_lat = 0 f_lat = 0
f_lon = 0 f_lon = 0

View file

@ -45,6 +45,8 @@ default_note_query_limit: 100
max_note_query_limit: 10000 max_note_query_limit: 10000
# Maximum value of open issues counter for moderators, anything equal or greater to this value "n" is shown as "n+" # Maximum value of open issues counter for moderators, anything equal or greater to this value "n" is shown as "n+"
max_issues_count: 99 max_issues_count: 99
# Maximum number of points in a GPX trace
max_trace_size: 1000000
# Zoom level to use for postcode results from the geocoder # Zoom level to use for postcode results from the geocoder
postcode_zoom: 15 postcode_zoom: 15
# Timeout for API calls in seconds # Timeout for API calls in seconds

View file

@ -6,8 +6,9 @@ module GPX
attr_reader :possible_points, :actual_points, :tracksegs attr_reader :possible_points, :actual_points, :tracksegs
def initialize(file) def initialize(file, options = {})
@file = file @file = file
@maximum_points = options[:maximum_points] || Float::INFINITY
end end
def parse_file(reader) def parse_file(reader)
@ -19,6 +20,7 @@ module GPX
if reader.name == "trkpt" if reader.name == "trkpt"
point = TrkPt.new(@tracksegs, reader["lat"].to_f, reader["lon"].to_f) point = TrkPt.new(@tracksegs, reader["lat"].to_f, reader["lon"].to_f)
@possible_points += 1 @possible_points += 1
raise FileTooBigError if @possible_points > @maximum_points
elsif reader.name == "ele" && point elsif reader.name == "ele" && point
point.altitude = reader.read_string.to_f point.altitude = reader.read_string.to_f
elsif reader.name == "time" && point elsif reader.name == "time" && point
@ -172,4 +174,10 @@ module GPX
longitude >= -180 && longitude <= 180 longitude >= -180 && longitude <= 180
end end
end end
class FileTooBigError < RuntimeError
def initialise
super("GPX File contains too many points")
end
end
end end

View file

@ -289,6 +289,18 @@ class TraceTest < ActiveSupport::TestCase
assert_equal 2, trace.size assert_equal 2, trace.size
end end
def test_import_enforces_limit
trace = create(:trace, :inserted => false, :fixture => "f")
with_settings(:max_trace_size => 1) do
assert_raise GPX::FileTooBigError do
trace.import
end
end
assert_not trace.inserted
end
private private
def check_query(query, traces) def check_query(query, traces)