[File] Possible ABI break when updating file from 5.33 to 5.35

Christos Zoulas christos at zoulas.com
Sat Jan 26 19:04:35 UTC 2019


Although those changes look scary, there is nothing to be concerned about:
1. the functions missing are not part of the ABI (and programs should not be using them)
2. the magic_set structure is not exposed in the ABI.

The only thing you need to make sure is that the magic database and the magic library are


> On Jan 26, 2019, at 11:14 AM, <emersonbernier at tutanota.com> <emersonbernier at tutanota.com> wrote:
> Hi!
> In freedesktop-sdk[1] we're trying to keep ABI compatibility when updating
> elements like file to new releases. In order to achieve this we use libabigail[2]
> tool to automate ABI compat checks. During update file from 5.33 to 5.35 (we
> missed 5.34 release) our tool produced following complaint:
> ╔════════════════╗
> ║ Comparing ABIs ║
> ╚════════════════╝
> ┌───────────────────────────────────┐
> │ ABI Break: libmagic.so.1:libmagic │
> └───────────────────────────────────┘
> Functions changes summary: 86 Removed, 1 Changed (15 filtered out), 0 Added functions
> Variables changes summary: 4 Removed, 0 Changed, 0 Added variables
> 86 Removed functions:
>   'function int buffer_apprentice(magic_set*, magic**, size_t*, size_t)'    {buffer_apprentice}
>   'function int buffer_fill(const buffer*)'    {buffer_fill}
>   'function void buffer_fini(buffer*)'    {buffer_fini}
>   'function void buffer_init(buffer*, int, void*, size_t)'    {buffer_init}
>   'function size_t cdf_count_chain(const cdf_sat_t*, cdf_secid_t, size_t)'    {cdf_count_chain}
>   'function char* cdf_ctime(const time_t*, char*)'    {cdf_ctime}
>   'function int cdf_find_stream(const cdf_dir_t*, const char*, int)'    {cdf_find_stream}
>   'function int cdf_print_classid(char*, size_t, const cdf_classid_t*)'    {cdf_print_classid}
>   'function int cdf_print_elapsed_time(char*, size_t, cdf_timestamp_t)'    {cdf_print_elapsed_time}
>   'function int cdf_print_property_name(char*, size_t, uint32_t)'    {cdf_print_property_name}
>   'function int cdf_read_dir(const cdf_info_t*, const cdf_header_t*, const cdf_sat_t*, cdf_dir_t*)'    {cdf_read_dir}
>   'function int cdf_read_doc_summary_info(const cdf_info_t*, const cdf_header_t*, const cdf_sat_t*, const cdf_sat_t*, const cdf_stream_t*, const cdf_dir_t*, cdf_stream_t*)'    {cdf_read_doc_summary_info}
>   'function int cdf_read_header(const cdf_info_t*, cdf_header_t*)'    {cdf_read_header}
>   'function int cdf_read_long_sector_chain(const cdf_info_t*, const cdf_header_t*, const cdf_sat_t*, cdf_secid_t, size_t, cdf_stream_t*)'    {cdf_read_long_sector_chain}
>   'function int cdf_read_property_info(const cdf_stream_t*, const cdf_header_t*, uint32_t, cdf_property_info_t**, size_t*, size_t*)'    {cdf_read_property_info}
>   'function int cdf_read_sat(const cdf_info_t*, cdf_header_t*, cdf_sat_t*)'    {cdf_read_sat}
>   'function ssize_t cdf_read_sector(const cdf_info_t*, void*, size_t, size_t, const cdf_header_t*, cdf_secid_t)'    {cdf_read_sector}
>   'function int cdf_read_sector_chain(const cdf_info_t*, const cdf_header_t*, const cdf_sat_t*, const cdf_sat_t*, const cdf_stream_t*, cdf_secid_t, size_t, cdf_stream_t*)'    {cdf_read_sector_chain}
>   'function ssize_t cdf_read_short_sector(const cdf_stream_t*, void*, size_t, size_t, const cdf_header_t*, cdf_secid_t)'    {cdf_read_short_sector}
>   'function int cdf_read_short_sector_chain(const cdf_header_t*, const cdf_sat_t*, const cdf_stream_t*, cdf_secid_t, size_t, cdf_stream_t*)'    {cdf_read_short_sector_chain}
>   'function int cdf_read_short_stream(const cdf_info_t*, const cdf_header_t*, const cdf_sat_t*, const cdf_dir_t*, cdf_stream_t*, const cdf_directory_t**)'    {cdf_read_short_stream}
>   'function int cdf_read_ssat(const cdf_info_t*, const cdf_header_t*, const cdf_sat_t*, cdf_sat_t*)'    {cdf_read_ssat}
>   'function int cdf_read_summary_info(const cdf_info_t*, const cdf_header_t*, const cdf_sat_t*, const cdf_sat_t*, const cdf_stream_t*, const cdf_dir_t*, cdf_stream_t*)'    {cdf_read_summary_info}
>   'function int cdf_read_user_stream(const cdf_info_t*, const cdf_header_t*, const cdf_sat_t*, const cdf_sat_t*, const cdf_stream_t*, const cdf_dir_t*, const char*, cdf_stream_t*)'    {cdf_read_user_stream}
>   'function void cdf_swap_class(cdf_classid_t*)'    {cdf_swap_class}
>   'function void cdf_swap_dir(cdf_directory_t*)'    {cdf_swap_dir}
>   'function void cdf_swap_header(cdf_header_t*)'    {cdf_swap_header}
>   'function int cdf_timespec_to_timestamp(cdf_timestamp_t*, const timespec*)'    {cdf_timespec_to_timestamp}
>   'function int cdf_timestamp_to_timespec(timespec*, cdf_timestamp_t)'    {cdf_timestamp_to_timespec}
>   'function uint16_t cdf_tole2(uint16_t)'    {cdf_tole2}
>   'function uint32_t cdf_tole4(uint32_t)'    {cdf_tole4}
>   'function uint64_t cdf_tole8(uint64_t)'    {cdf_tole8}
>   'function char* cdf_u16tos8(char*, size_t, const uint16_t*)'    {cdf_u16tos8}
>   'function int cdf_unpack_catalog(const cdf_header_t*, const cdf_stream_t*, cdf_catalog_t**)'    {cdf_unpack_catalog}
>   'function void cdf_unpack_dir(cdf_directory_t*, char*)'    {cdf_unpack_dir}
>   'function void cdf_unpack_header(cdf_header_t*, char*)'    {cdf_unpack_header}
>   'function int cdf_unpack_summary_info(const cdf_stream_t*, const cdf_header_t*, cdf_summary_info_header_t*, cdf_property_info_t**, size_t*)'    {cdf_unpack_summary_info}
>   'function int cdf_zero_stream(cdf_stream_t*)'    {cdf_zero_stream}
>   'function int der_cmp(magic_set*, magic*)'    {der_cmp}
>   'function int32_t der_offs(magic_set*, magic*, size_t)'    {der_offs}
>   'function int file_apprentice(magic_set*, const char*, int)'    {file_apprentice}
>   'function int file_ascmagic(magic_set*, const buffer*, int)'    {file_ascmagic}
>   'function int file_ascmagic_with_encoding(magic_set*, const buffer*, unichar*, size_t, const char*, const char*, int)'    {file_ascmagic_with_encoding}
>   'function void file_badread(magic_set*)'    {file_badread}
>   'function void file_badseek(magic_set*)'    {file_badseek}
>   'function int file_buffer(magic_set*, int, const char*, void*, size_t)'    {file_buffer}
>   'function int file_check_mem(magic_set*, unsigned int)'    {file_check_mem}
>   'function int file_encoding(magic_set*, const buffer*, unichar**, size_t*, const char**, const char**, const char**)'    {file_encoding}
>   'function void file_error(magic_set*, int, const char*, ...)'    {file_error}
>   'function const char* file_fmttime(uint64_t, int, char*)'    {file_fmttime}
>   'function int file_fsmagic(magic_set*, const char*, stat*)'    {file_fsmagic}
>   'function const char* file_getbuffer(magic_set*)'    {file_getbuffer}
>   'function int file_is_tar(magic_set*, const buffer*)'    {file_is_tar}
>   'function int file_looks_utf8(const unsigned char*, size_t, unichar*, size_t*)'    {file_looks_utf8}
>   'function void file_magerror(magic_set*, const char*, ...)'    {file_magerror}
>   'function int file_magicfind(magic_set*, const char*, mlist*)'    {file_magicfind}
>   'function void file_magwarn(magic_set*, const char*, ...)'    {file_magwarn}
>   'function void file_mdump(magic*)'    {file_mdump}
>   'function magic_set* file_ms_alloc(int)'    {file_ms_alloc}
>   'function void file_ms_free(magic_set*)'    {file_ms_free}
>   'function void file_oomem(magic_set*, size_t)'    {file_oomem}
>   'function int file_pipe2file(magic_set*, int, void*, size_t)'    {file_pipe2file}
>   'function char* file_pop_buffer(magic_set*, file_pushbuf_t*)'    {file_pop_buffer}
>   'function char* file_printable(char*, size_t, const char*)'    {file_printable}
>   'function size_t file_printedlen(const magic_set*)'    {file_printedlen}
>   'function int file_printf(magic_set*, const char*, ...)'    {file_printf}
>   'function size_t file_pstring_get_length(const magic*, const char*)'    {file_pstring_get_length}
>   'function size_t file_pstring_length_size(const magic*)'    {file_pstring_length_size}
>   'function file_pushbuf_t* file_push_buffer(magic_set*)'    {file_push_buffer}
>   'function int file_regcomp(file_regex_t*, const char*, int)'    {file_regcomp}
>   'function void file_regerror(file_regex_t*, int, magic_set*)'    {file_regerror}
>   'function int file_regexec(file_regex_t*, const char*, size_t, regmatch_t*, int)'    {file_regexec}
>   'function void file_regfree(file_regex_t*)'    {file_regfree}
>   'function int file_replace(magic_set*, const char*, const char*)'    {file_replace}
>   'function int file_reset(magic_set*, int)'    {file_reset}
>   'function void file_showstr(FILE*, const char*, size_t)'    {file_showstr}
>   'function uint64_t file_signextend(magic_set*, magic*, uint64_t)'    {file_signextend}
>   'function int file_softmagic(magic_set*, const buffer*, uint16_t*, uint16_t*, int, int)'    {file_softmagic}
>   'function int file_trycdf(magic_set*, const buffer*)'    {file_trycdf}
>   'function int file_tryelf(magic_set*, const buffer*)'    {file_tryelf}
>   'function int file_vprintf(magic_set*, const char*, __va_list_tag*)'    {file_vprintf}
>   'function int file_zmagic(magic_set*, const buffer*, const char*)'    {file_zmagic}
>   'function const char* fmtcheck(const char*, const char*)'    {fmtcheck}
>   'function ssize_t sread(int, void*, size_t, int)'    {sread}
>   'function size_t strlcat(char*, const char*, size_t)'    {strlcat}
>   'function size_t strlcpy(char*, const char*, size_t)'    {strlcpy}
> 1 function with some indirect sub-type change:
>   [C]'function const char* magic_buffer(magic_set*, void*, size_t)' at magic.c:524:1 has some indirect sub-type changes:
>     parameter 1 of type 'magic_set*' has sub-type changes:
>       in pointed to type 'struct magic_set' at file.h:400:1:
>         type size changed from 1920 to 1984 (in bits)
>         1 data member insertion:
>           'mode_t magic_set::mode', at offset 704 (in bits) at file.h:419:1
>         9 data member changes:
>          'struct {const char* s; size_t s_len; size_t offset; size_t rm_len;} magic_set::search' offset changed from 704 to 768 (in bits) (by +64 bits)
>          'VALUETYPE magic_set::ms_value' offset changed from 960 to 1024 (in bits) (by +64 bits)
>          'uint16_t magic_set::indir_max' offset changed from 1728 to 1792 (in bits) (by +64 bits)
>          'uint16_t magic_set::name_max' offset changed from 1744 to 1808 (in bits) (by +64 bits)
>          'uint16_t magic_set::elf_shnum_max' offset changed from 1760 to 1824 (in bits) (by +64 bits)
>          'uint16_t magic_set::elf_phnum_max' offset changed from 1776 to 1840 (in bits) (by +64 bits)
>          'uint16_t magic_set::elf_notes_max' offset changed from 1792 to 1856 (in bits) (by +64 bits)
>          'uint16_t magic_set::regex_max' offset changed from 1808 to 1872 (in bits) (by +64 bits)
>          'size_t magic_set::bytes_max' offset changed from 1856 to 1920 (in bits) (by +64 bits)
> 4 Removed variables:
>   'int file_formats[49]'    {file_formats}
>   'const char* file_names[]'    {file_names}
>   'const size_t file_nformats'    {file_nformats}
>   'const size_t file_nnames'    {file_nnames}
> As part of our discussion[3] about what to do with that we would like to ask
> about your opinion on the matter. Especially I wanted to ask if reported changes
> were intentional and if they're safe for backward compatibility thus if above
> report is a false positive. I would be grateful if you can find time to respond.
> Thank you.
> [1] https://gitlab.com/freedesktop-sdk <https://gitlab.com/freedesktop-sdk>
> [2] https://sourceware.org/libabigail <https://sourceware.org/libabigail>
> [3] https://gitlab.com/freedesktop-sdk/freedesktop-sdk/merge_requests/900 <https://gitlab.com/freedesktop-sdk/freedesktop-sdk/merge_requests/900>
> -- 
> File mailing list
> File at astron.com
> https://mailman.astron.com/mailman/listinfo/file

More information about the File mailing list