The doc of `size` argument of `FileStream.read()` is wrong
According to https://valadoc.org/glib-2.0/GLib.FileStream.write.html, FileStream.read()
accepts 2 argument, first is an array to read, and second is a size
, which is "the number of the objects to be read".
And according to that, if we have var buf = new uint16[100];
, we should call stream.read(buf, 100);
to fill it. But that mismatches its VAPI file, which is defined as following:
[CCode (cname = "fread", instance_pos = -1)]
public size_t read ([CCode (array_length_pos = 2.1)] uint8[] buf, size_t size = 1);
Compared with the C fread()
prototype: size_t fread(void ptr[restrict .size * .nmemb], size_t size, size_t nmemb, FILE *restrict stream);
, the vala size
argument should be exactly C size
argument, which means size of one object in array, and the C nmemb
argument which actually means the number of objects to read, is filled by vala compiler automatically.
I suspect the valadoc is wrong, because 1. we can get array length by attributes, but cannot know object size because we already cast the argument to uint8
type, 2. the example code in valadoc of FileStream.write()
and FileStream.read()
also treats size
as one object size (the C size
argument) instead of the array length (the C nmemb
argument).
Also, if the valadoc is correct, and we write code according to it (pass array length as size), we finally get codes that may leads into overflow, for example such vala code:
public static int main(string[] args) {
var stream = FileStream.open("vala-fread-test", "r");
var len = 10;
var buf = new uint16[len];
stream.read((uint8[])buf, len);
return 0;
}
Generates following C code with vala -C
:
/* test-vala-fread.c generated by valac 0.56.3, the Vala compiler
* generated from test-vala-fread.vala, do not modify */
#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include <stdio.h>
#include <glib/gstdio.h>
#define _fclose0(var) ((var == NULL) ? NULL : (var = (fclose (var), NULL)))
static gint _vala_main (gchar** args,
gint args_length1);
static gint
_vala_main (gchar** args,
gint args_length1)
{
FILE* stream = NULL;
FILE* _tmp0_;
gint len = 0;
guint16* buf = NULL;
guint16* _tmp1_;
gint buf_length1;
gint _buf_size_;
gint result;
_tmp0_ = g_fopen ("vala-fread-test", "r");
stream = _tmp0_;
len = 10;
_tmp1_ = g_new0 (guint16, len);
buf = _tmp1_;
buf_length1 = len;
_buf_size_ = buf_length1;
fread ((guint8*) buf, (gsize) len, (gint) ((buf_length1 * sizeof (guint16)) / sizeof (guint8)), stream);
result = 0;
buf = (g_free (buf), NULL);
_fclose0 (stream);
return result;
}
int
main (int argc,
char ** argv)
{
return _vala_main (argv, argc);
}
What we expect is to read 20
bytes, but the code is actually reading 200
bytes, so the valadoc of size
must be incorrect, if someone reads the doc carefully and then write code, it leads into a bug. This already happens in GNOME Boxes: https://gitlab.gnome.org/GNOME/gnome-boxes/-/blob/main/src/archive-writer.vala#L121.
I suggest to modify the valadoc page to match the actual behavior, but if you guys have other concerns please tell me, thanks!
NOTE: I've updated this issue to describe the problem better.