Smtk2ssrf has a segfault which matches quite well glibc's
CVE-2019-6488 (except for the x32 part).
It came from a call to memcpy in mdb_ole_read() func, used to get the
header and the profile of a dive from the database.
May be it could be fixed in libmdb but Mdbtools project has been stalled
for the past 5 years so ...
The segfault seems to be triggered by an empty profile in the first dive
in the database (a pretty common case in older Aladin DCs due to their
little memmory). The only special thing here is the fact it's the first
dive in the database structure (not the first by its index).
We can avoid the crash if we don't call mdb_ole_read_full() func on zero
sized profile field.
The problem here is we can't get the size of the fields and build the
MdbColumn in the same roud. Happily we just need the MdbColumn struct
for the dive profile and header. So, we can change the previous approach
using MdbColumns through almost all functions to a simpler one using the
already bounded strings by smtk_open_table() and just using the
col[n]->bind_pointer in the main function where the columns are built to
be used by mdb_ole_read_full().
Reported-by: Robert C. Helling <helling@atdotde.de>
Signed-off-by: Salvador Cuñat <salvador.cunat@gmail.com>
Under some circustances values stored in this arrays may be NULL or even
previously freed. Check them to avoid further crashes.
Signed-off-by: Salvador Cuñat <salvador.cunat@gmail.com>
The d->cylinders created will be overriden by libdivecomputer parsing,
resulting in 0, 1 , may be 2 cylinders depending on DC data. This is not
what we want when importing a divelog, because we will miss all hand
entered tanks.
BTW, using get_cylinder() on tank number bigger than created, results in
a NULL pointer and a crash.
As we can't foresee how many tanks (or even it's positional numbers in
log) a diver has used, the full 10 tanks supported by SmarTrak can be
easily created and parsed using get_or_create_cylinder(), and unused
cleaned later.
Signed-off-by: Salvador Cuñat <salvador.cunat@gmail.com>
Grammar-nazi ran
git grep -l 'indexes' | xargs sed -i '' -e 's/indexes/indices/g'
to prevent future wincing when reading the source code.
Unfortunatly, Qt itself is infected as in
QModelIndexList QItemSelection::indexes() const
Signed-off-by: Robert C. Helling <helling@atdotde.de>
Instead of accessing the cylinder table directly, use the get_cylinder()
function. This gives less unwieldy expressions. But more importantly,
the function does bound checking. This is crucial for now as the code
hasn't be properly audited since the change to arbitrarily sized
cylinder tables. Accesses of invalid cylinder indexes may lead to
silent data-corruption that is sometimes not even noticed by
valgrind. Returning NULL instead of an invalid pointer will make
debugging much easier.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Instead of using fixed size arrays, use a new cylinder_table structure.
The code copies the weightsystem code, but is significantly more complex
because cylinders are such an integral part of the core.
Two functions to access the cylinders were added:
get_cylinder() and get_or_create_cylinder()
The former does a simple array access and supposes that the cylinder
exists. The latter is used by the parser(s) and if a cylinder with
the given id does not exist, cylinders up to that id are generated.
One point will make C programmers cringe: the cylinder structure is
passed by value. This is due to the way the table-macros work. A
refactoring of the table macros is planned. It has to be noted that
the size of a cylinder_t is 64 bytes, i.e. 8 long words on a 64-bit
architecture, so passing on the stack is probably not even significantly
slower than passing as reference.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
As Berthold points out, a failure to match the site or location index
will result in an infinite loop with previous patch.
With this one the loop will end after reading the last table row even if
no idx is matched. But ... If we asume this situation is possible the
retrieved data would be wrong, and ending the function without filling
the site structure is mandatory too.
Signed-off-by: Salvador Cuñat <salvador.cunat@gmail.com>
We were assuming these tables were sorted with their indexes, but it
happens to be false, under some circustances at least.
Reported-by: Andreas Hagberg <scubasoft@gmail.com>
Signed-off-by: Salvador Cuñat <salvador.cunat@gmail.com>
Replace the fixed-size weightsystem table by a dynamically
relocated table. Reuse the table-macros used in other parts
of the code.
The table stores weightsystem entries, not pointers to
weightsystems. Thus, ownership of the description string is
taken when adding a weightsystem. An extra function adds
a cloned weightsystem at the end of the table.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Make dive.h a bit slimmer. It's only a drop in the bucket - but at
least when modifying tag functions not the *whole* application is
rebuilt anymore.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Remove a few cases of
void fun() {
...
}
While touching these functions, fix a few other whitespace
coding style violations.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Since the UUID will be overwritten on save and is only used on save
and load, set it only on save or load. For other created dive sites,
leave the UUID field uninitialized.
This means that the UUID will change between saves. Let's see how
the git saver handles that.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
To enable undo of dive site functions, it is crucial to work
with different dive site tables. Therefore add a dive site table
parameter to dive site functions. For now, always pass the global
dive site table. Thus, this commit shouldn't alter any functionality.
After this change, a simple search for dive_site_table reveals all
places where the global dive site table is accessed.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
add_to_string() frees the original string that is passed in. This
should therefore not be of "const char *" type, as the contents
of the string *will* be modified (or more precisely: destroyed).
Same for the congener smtk_concat_str().
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Rename
- dive_get_insertion_index() -> dive_table_get_insertion_index()
- unregister_dive_from_table() -> remove_from_dive_table()
- get_idx_in_table() -> get_idx_in_dive_table()
- sort_table() -> sort_dive_table()
This will make it more straight-forward to generate these functions
from macros.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Replace the UUID reference of struct dive by a pointer to dive_site.
This commit is rather large in lines, but nevertheless quite simple
since most of the UUID->pointer work was done in previous commits.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This changes more of the dive-site interface to return pointers
instead of UUIDs. Currently, most call sites directly extract
UUIDs afterwards. Ultimately, the UUIDs will be generally replaced
by pointers, which will then simplify these callers.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
As a first step in removing dive-site uuids, change the interface
of the get_dive_site_*() functions to return pointers instead
of uuids. This makes code a bit more complicated in places where
the uuid is extracted afterwards (needed NULL check). Nevertheless,
these places should disappear once pointers instead of uuids are
stored in the dive-structures.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Instead of having people treat latitude and longitude as separate
things, just add a 'location_t' data structure that contains both.
Almost all cases want to always act on them together.
This is really just prep-work for adding a few more locations that we
track: I want to add a entry/exit location to each dive (independent of
the dive site) because of how the Garmin Descent gives us the
information (and hopefully, some day, other dive computers too).
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
And add a fuction to parse tables that are not "relational", meaning
tables which are directly refered from Dives table.
Signed-off-by: Salvador Cuñat <salvador.cunat@gmail.com>
We can allocate fixed size arrays for smartrak tables as its size can
be known in advance. Simply reading table->num_rows is too dangereous
as smartrak tables have "holes" commonly. This is, they can look like:
Idx | Txt
1 | blablabla
2 | blebleble
4 | blobloblo
table->num_rows would give us 3, but we need to allocate 4 to get an
array like:
|0|blablabla |1|blebleble |2| |3|blobloblo
as the idea is to use the table index to reference the array data.
Signed-off-by: Salvador Cuñat <salvador.cunat@gmail.com>
Previously we built arrays for the tables each time we parsed a dive.
Now we simply build the lists once, and use them in each dive parsing.
Signed-off-by: Salvador Cuñat <salvador.cunat@gmail.com>
In most cases we can not foresee the maximum number of data of a given
type. It can be quite low or really big (a concerned diver can store
thousands of different fishes in Fish table).
Moving from arrays, where size has to be preset, to linked lists seems
the more logical option.
Here we set a (very limited) data structure, just an index and a text
fields following the format of most SmartTrak tables. Some special
table, like Buddy, needs a bit of processing before placing the data in
the list.
Signed-off-by: Salvador Cuñat <salvador.cunat@gmail.com>
In a previous commit, the get_gasmix_* functions were changed to
return by value. For consistency, also pass gasmix by value.
Note that on common 64-bit platforms struct gasmix is the size
of a pointer [2 * 32 bit vs. 64 bit] and therefore uses the
same space on the stack. On 32-bit platforms, the stack use
is probably doubled, but in return a dereference is avoided.
Supporting arbitrary gas-mixes (H2, Ar, ...) will be such an
invasive change that going back to pointers is probably the
least of our worries.
This commit is a step in const-ifying input parameters (passing
by value is the ultimate way of signaling that the input parameter
will not be changed [unless there are references to said parameter]).
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Mostly replace "return (expression);" by "return expression;" and one
case of "function((parameter))" by "function(parameter)".
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
There are ca. 50 constructs of the kind
same_string(s, "")
to test for empty or null strings. Replace them by the new helper
function empty_string().
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
As Lubomir pointed out in his patch for datatrak.c, the format option %m
for sscanf doesn't work in mingw/windows. Fortunately it's unnecessary
as dates are dropped and we just get times.
Signed-off-by: Salvador Cuñat <salvador.cunat@gmail.com>
For different reasons some used functions aren't portable or simply are
not included in mingw. This includes index, rindex, strptime, and
timegm.
A workaround for this is needed, if we want to build for windows using
mingw based mxe environment. This patch does:
- drops index and rindex in favor of strchr and strrchr
- substitute strptime with a sscanf parsing
- emulate timegm with a private func smtk_timegm()
- remove definitions needed by strptime
Signed-off-by: Salvador Cuñat <salvador.cunat@gmail.com>
Curly braces are necessary in nested conditionals or results may not be
those expected. In this case, the "else" clause applied on second "if",
instead of first one.
Signed-off-by: Salvador Cuñat <salvador.cunat@gmail.com>
SmartTrak's bookmarks work in the same fashion Subsurface's do. The user
may set a bookmark while underwater or set it just on the divelog
software.
At this time we are parsing those set in the DC twice, as we get one
from libdivecomputer and another from smarttrak's database.
This patch just checks if we have a bookmark event downloaded by
libdivecomputer which has the same time that the one parsed from the
.slg file. If so, merge the names taking the one from smarttrak.
Text from smarttrak is preferred because the user may have entered some
interesting note there and libdivecomputer's name is just "bookmark".
Signed-off-by: Salvador Cuñat <salvador.cunat@gmail.com>
It was assumed that every data field in a wreck table was filled or
zeroed. This assumption is actually false, so this patch adds testing
for the existence of strings before working with them.
Signed-off-by: Salvador Cuñat <salvador.cunat@gmail.com>
Until now, we did the cylinder import based on its initial pressure (a
tank without pressure is an unused tank). Based in this assumption, we
just dropped those tanks whose initial press was 0, losing user
introduced tank definitions and getting some duplicities due to one
cylinder being numbered (e.g.) 2 by libdivecomputer and 3 by SmartTrak.
The new workflow is: get every single tank reported by SmartTrak (giving
preference to libdivecomputer parsed data), then clean the cylinder
table reverse order, dropping tanks without description and init or end
pressures, and checkig them against the previous cylinder to do a merge,
if they look the same, and try to avoid duplicities.
The new logic assumes a heavier workload for the benefit of lower data
loss (e.g. a user may get his/her tanks descriptions despite he/she
hasn't recorded their pressures because forgot the values or had an issue
with the gas transmitter).
Suggested-by: Alessandro Volpi <volpial@gmail.com>
Signed-off-by: Salvador Cuñat <salvador.cunat@gmail.com>
In the past subsurface managed up to 8 tanks, but now it manages up to
20. SmartTrak manages 10 (3 in older no trimix versions) so there is no
more need to drop the last tanks.
Signed-off-by: Salvador Cuñat <salvador.cunat@gmail.com>
The cylinder info is built one by one. This way, instead of passing dive
and tank number parameters, just passing a pointer to the tank been
worked seems preferable.
It also introduces lrint() in the function to round the doubles values
obtained from libmdb for tank size and workingpressure.
Signed-off-by: Salvador Cuñat <salvador.cunat@gmail.com>
Framed in a full rework of the cylinders info import management, this
funcs will be used in next patches.
Functions merge_cylinder_type(), merge_cylinder_mix() and
merge_cylinder_info(), have been shamelessly copied from dive.c as they
have been removed by 162767aa dated 2017-03-11 just when I was going to
use them.
Macros MERGE_MAX() and MERGE_MIN() have just been copied from dive.c,
but they could be moved to dive.h so they could be used elsewhere if
needed.
Signed-off-by: Salvador Cuñat <salvador.cunat@gmail.com>
As commented on mailing list. Most numerical values from libmdb are
doubles obtained via strtod(), so, rounding them instead of just
truncating seems the correct way.
Signed-off-by: Salvador Cuñat <salvador.cunat@gmail.com>
User can manually add bookmarks on the profile display of SmartTrak.
These are stored in a table with column names which made me think of
cartesian spatial coordinates. In the end the X coordinate is the time.
This makes possible to build subsurface events in those moments of the
dive. The other interesting data is just the text entered by the user.
Suggested-by: Alessandro Volpi <volpial@gmail.com>
Signed-off-by: Salvador Cuñat <salvador.cunat@gmail.com>
Fixes some memory leaks, most of them excesive use of copy_string() in
places where it was unnecesary.
Signed-off-by: Salvador Cuñat <salvador.cunat@gmail.com>