Bug 9320 - PVS-Studio
Summary: PVS-Studio
Status: RESOLVED FIXED
Alias: None
Product: Samba 4.0
Classification: Unclassified
Component: Other (show other bugs)
Version: unspecified
Hardware: All All
: P5 normal (vote)
Target Milestone: ---
Assignee: Andrew Bartlett
QA Contact: Samba QA Contact
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-10-23 11:48 UTC by Andrey
Modified: 2022-01-26 23:00 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Andrey 2012-10-23 11:48:02 UTC
A few months ago, I check the Samba project by use PVS-Studio tool. But I forgot write about issues. Now remembered and decided to send. Maybe some bugs still present in the code.

-------------------------------------------------------------------------------
samba

V501 There are identical sub-expressions 'ace->type == SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT' to the left and to the right of the '||' operator. sddl.c 528

static char *sddl_encode_ace(TALLOC_CTX *mem_ctx, const struct security_ace *ace,
           const struct dom_sid *domain_sid)
{
  ....
  if (ace->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT ||
      ace->type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT ||
      ace->type == SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT ||
      ace->type == SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT) {
  ....
}
-------------------------------------------------------------------------------
samba

V501 There are identical sub-expressions to the left and to the right of the '!=' operator: s1_len != s1_len pdbtest.c 106

static bool samu_correct(struct samu *s1, struct samu *s2)
{
  ....
  } else if (s1_len != s1_len) {
    DEBUG(0, ("Password history not written correctly, lengths differ, want %d, got %d\n",
          s1_len, s2_len));
    ret = False;
  }
  ....
}
-------------------------------------------------------------------------------
samba

V501 There are identical sub-expressions to the left and to the right of the '>' operator: data > data t_asn1.c 45

int main(void)
{
  ....
    if ((data->length != tests[i].length) ||
        (memcmp(data>data, tests[i].data, data->length) != 0)) {
      printf("Test for %d failed\n", values[i]);
      ok = False;
    }
  ....
}

#info
Most likely this is what should be written here: data->data.
-------------------------------------------------------------------------------
samba

V501 There are identical sub-expressions to the left and to the right of the '>' operator: i2->pid > i2->pid brlock.c 1901

static int compare_procids(const void *p1, const void *p2)
{
  const struct server_id *i1 = (struct server_id *)p1;
  const struct server_id *i2 = (struct server_id *)p2;

  if (i1->pid < i2->pid) return -1;
  if (i2->pid > i2->pid) return 1;
  return 0;
}
-------------------------------------------------------------------------------
samba

V511 The sizeof() operator returns size of the pointer, and not of the array, in 'sizeof ((domain))' expression. wbinfo.c 124
V511 The sizeof() operator returns size of the pointer, and not of the array, in 'sizeof ((user))' expression. wbinfo.c 125

#define FSTRING_LEN 256
typedef char fstring[FSTRING_LEN];

char *safe_strcpy(char *dest,const char *src, size_t maxlength)
#define fstrcpy(d,s) safe_strcpy((d),(s),sizeof(fstring)-1)

static bool parse_wbinfo_domain_user(
  const char *domuser, fstring domain, fstring user)
{
  ....
    /* Maybe it was a UPN? */
    if ((p = strchr(domuser, '@')) != NULL) {
      fstrcpy(domain, "");
      fstrcpy(user, domuser);
      return true;
    }
  ....
}

#add
V511 The sizeof() operator returns size of the pointer, and not of the array, in 'sizeof ((user))' expression. wbinfo.c 129
V511 The sizeof() operator returns size of the pointer, and not of the array, in 'sizeof ((domain))' expression. wbinfo.c 130
V511 The sizeof() operator returns size of the pointer, and not of the array, in 'sizeof ((user))' expression. wbinfo.c 134
V511 The sizeof() operator returns size of the pointer, and not of the array, in 'sizeof ((domain))' expression. wbinfo.c 135
V511 The sizeof() operator returns size of the pointer, and not of the array, in 'sizeof ((fqdn))' expression. util.c 2215
V511 The sizeof() operator returns size of the pointer, and not of the array, in 'sizeof ((fqdn))' expression. util.c 2243
V511 The sizeof() operator returns size of the pointer, and not of the array, in 'sizeof ((srv_name))' expression. namequery_dc.c 137
V511 The sizeof() operator returns size of the pointer, and not of the array, in 'sizeof ((unname))' expression. nmbd_workgroupdb.c 55
V511 The sizeof() operator returns size of the pointer, and not of the array, in 'sizeof ((unname))' expression. nmbd_workgroupdb.c 59
V511 The sizeof() operator returns size of the pointer, and not of the array, in 'sizeof ((sharename))' expression. printing.c 133
V511 The sizeof() operator returns size of the pointer, and not of the array, in 'sizeof (new_name)' expression. mangle_hash2.c 705
V511 The sizeof() operator returns size of the pointer, and not of the array, in 'sizeof ((user))' expression. password.c 647
V511 The sizeof() operator returns size of the pointer, and not of the array, in 'sizeof ((user))' expression. password.c 685
V511 The sizeof() operator returns size of the pointer, and not of the array, in 'sizeof ((user))' expression. password.c 698
V511 The sizeof() operator returns size of the pointer, and not of the array, in 'sizeof ((user))' expression. password.c 717
V511 The sizeof() operator returns size of the pointer, and not of the array, in 'sizeof ((name))' expression. net_rpc_rights.c 54
V511 The sizeof() operator returns size of the pointer, and not of the array, in 'sizeof ((dcname))' expression. winbindd_cm.c 702
V511 The sizeof() operator returns size of the pointer, and not of the array, in 'sizeof ((user))' expression. winbindd_util.c 864
V511 The sizeof() operator returns size of the pointer, and not of the array, in 'sizeof ((domain))' expression. winbindd_util.c 867
V511 The sizeof() operator returns size of the pointer, and not of the array, in 'sizeof ((domain))' expression. winbindd_util.c 869
V511 The sizeof() operator returns size of the pointer, and not of the array, in 'sizeof ((user))' expression. winbindd_util.c 875
V511 The sizeof() operator returns size of the pointer, and not of the array, in 'sizeof ((domain))' expression. winbindd_util.c 876
V511 The sizeof() operator returns size of the pointer, and not of the array, in 'sizeof ((key))' expression. mapfile.c 90
V511 The sizeof() operator returns size of the pointer, and not of the array, in 'sizeof ((value))' expression. mapfile.c 91
-------------------------------------------------------------------------------
samba

V512 A call of the 'memset' function will lead to underflow of the buffer 'rt'. perf_writer.c 80

void initialize(PERF_DATA_BLOCK *data,
  RuntimeSettings *rt, int argc, char **argv)
{
    memset(data, 0, sizeof(*data));
    memset(rt, 0, sizeof(*data));
  ....
}

#info
Most likely this is what should be written here: memset(rt, 0, sizeof(*rt));.
-------------------------------------------------------------------------------
samba

V512 A call of the 'memcmp' function will lead to underflow of the buffer 'u0'. netuser.c 247

static NET_API_STATUS test_netusermodals(struct libnetapi_ctx *ctx,
           const char *hostname)
{
  ....
  struct USER_MODALS_INFO_0 *u0 = NULL;
  struct USER_MODALS_INFO_0 *_u0 = NULL;
  ....
  if (memcmp(u0, _u0, sizeof(u0) != 0)) {
    printf("USER_MODALS_INFO_0 struct has changed!!!!\n");
    return -1;
  }
  ....
}

#info
Most likely this is what should be written here: sizeof(*u0).
-------------------------------------------------------------------------------
samba

V523 The 'then' statement is equivalent to the 'else' statement. reg_perfcount.c 1092

static uint32 reg_perfcount_get_perf_data_block(....)
{
  ....
  if(object_ids == NULL)
  {
    /* we're getting a request for "Global" here */
    retval = _reg_perfcount_assemble_global(block, mem_ctx, base_index, names);
  }
  else
  {
    /* we're getting a request for a specific set of PERF_OBJECT_TYPES */
    retval = _reg_perfcount_assemble_global(block, mem_ctx, base_index, names);
  }
  ....
}
-------------------------------------------------------------------------------
samba

V547 Expression '(to != CH_UTF16LE) || (to != CH_UTF16BE)' is always true. Probably the '&&' operator should be used here. charcnv.c 188

static size_t convert_string_internal(....)
{
  ....
    if (((from == CH_UTF16LE)||(from == CH_UTF16BE)) &&
        ((to != CH_UTF16LE)||(to != CH_UTF16BE))) {
  ....
}

#add
V547 Expression '(to != CH_UTF16LE) || (to != CH_UTF16BE)' is always true. Probably the '&&' operator should be used here. charcnv.c 599
-------------------------------------------------------------------------------
samba

V547 Expression 'result.pid < 0' is always false. Unsigned type value is never < 0. util.c 2376

struct server_id {
  uint32_t pid;
  uint32_t vnn;
  uint64_t unique_id;
}

struct server_id interpret_pid(const char *pid_string)
{
  struct server_id result;
  ....
  /* Assigning to result.pid may have overflowed
     Map negative pid to -1: i.e. error */
  if (result.pid < 0) {
    result.pid = -1;
  }
  ....
}
-------------------------------------------------------------------------------
samba

V547 Expression is always false. Consider reviewing this expression. pdbtest.c 170

static bool samu_correct(struct samu *s1, struct samu *s2)
{
  ....
  if (d2_buf == NULL && d2_buf != NULL) {
    DEBUG(0, ("Logon hours is not set\n"));
    ret = False;
  }
  ....
}
-------------------------------------------------------------------------------
samba

V597 The compiler could delete the 'memset' function call, which is used to flush 'x' buffer. The RtlSecureZeroMemory() function should be used to erase the private data. md2.c 91

static void
calc(struct md2 *m, const void *v)
{
  unsigned char x[48], L;
  ....
  memset(x, 0, sizeof(x));
}

#add
V597 The compiler could delete the 'memset' function call, which is used to flush 'buf' buffer. The RtlSecureZeroMemory() function should be used to erase the private data. rand-fortuna.c 291
V597 The compiler could delete the 'memset' function call, which is used to flush 'hash' buffer. The RtlSecureZeroMemory() function should be used to erase the private data. rand-fortuna.c 341
V597 The compiler could delete the 'memset' function call, which is used to flush 'buf' buffer. The RtlSecureZeroMemory() function should be used to erase the private data. rand-fortuna.c 378
V597 The compiler could delete the 'memset' function call, which is used to flush 'k' buffer. The RtlSecureZeroMemory() function should be used to erase the private data. rc2.c 110
-------------------------------------------------------------------------------
samba

V610 Undefined behavior. Check the shift operator '<<. The left operand '~0' is negative. idtree.c 284

static void *_idr_find(struct idr_context *idp, int id)
{
  ....
  if (n + IDR_BITS < 31 &&
      ((id & ~(~0 << MAX_ID_SHIFT)) >> (n + IDR_BITS))) {
    return NULL;
  }
  ....
}
-------------------------------------------------------------------------------
samba

V627 Consider inspecting the expression. The argument of sizeof() is the macro which expands to a number. regfio.c 1470

#define HBIN_HDR_SIZE    4

char header[HBIN_HDR_SIZE];

static REGF_HBIN* regf_hbin_allocate( REGF_FILE *file, uint32 block_size )
{
  REGF_HBIN *hbin;
  ....
  memcpy( hbin->header, "hbin", sizeof(HBIN_HDR_SIZE) );
  ....
}

#info
It works. Good luck: sizeof(4) == 4.
-------------------------------------------------------------------------------
samba

V595 The 'ctx' pointer was utilized before it was verified against nullptr. Check lines: 67, 72. cm.c 67

static WERROR libnetapi_open_ipc_connection(struct libnetapi_ctx *ctx,
              const char *server_name,
              struct client_ipc_connection **pp)
{
  struct libnetapi_private_ctx *priv_ctx =
    (struct libnetapi_private_ctx *)ctx->private_data;
  struct user_auth_info *auth_info = NULL;
  struct cli_state *cli_ipc = NULL;
  struct client_ipc_connection *p;

  if (!ctx || !pp || !server_name) {
    return WERR_INVALID_PARAM;
  }
  ....
}
-------------------------------------------------------------------------------
samba

V579 The memset function receives the pointer and its size as arguments. It is possibly a mistake. Inspect the third argument. reg_perfcount.c 945

static bool _reg_perfcount_init_data_block(....)
{
  smb_ucs2_t *temp = NULL;
  ....
  memset(temp, 0, sizeof(temp));
  ....
}

#info
Most likely this is what should be written here: sizeof(*temp).

#add
V579 The cli_api function receives the pointer and its size as arguments. It is possibly a mistake. Inspect the seventh argument. clirap2.c 331
V579 The memset function receives the pointer and its size as arguments. It is possibly a mistake. Inspect the third argument. engine.c 91
V579 The memset function receives the pointer and its size as arguments. It is possibly a mistake. Inspect the third argument. md2.c 133
Comment 1 Douglas Bagnall 2021-12-09 05:47:08 UTC
Unless otherwise noted, the listed bugs are variously fixed in these commits. Many were fixed before the report.

Aurelien Aptel was a prolific fixer.


caff67082a22b4b5250eb73b09e57bb9ab99c346
ac7de8021050e560d39f613ea4a2caab06c7a2a8
t_asn1.c gone in 961952ee643ab82738840a29cec87c925e91d8c9
compare_procids() gone in 871bb7562cad1d4a9dccab602880d2ef3fffd75c, fixed before that
[1] see below
0fa9f347fd401baad6e2b65d5e4706f458cf5ba4
1f9d1f9cd70b4e9b41e53d9cca5025ed31ef7e71
e80891db4123a2ae326517c27c559ace18b0f05b or earlier
15e84a9a09c5a86416e964a3258ee35718fbf45a
d01dbd6c3fd9ca2595d65991b56db4400a35ece0
[2] extant!
[3] extant!
0d08af70c83f98bf0daeef45a0d76676a1fbde5a
d58aa46c08f69b1b048375b0eea85bdf25f99cda
ab37eae79c564ee903ca85c2d997093e17b1de98
bd5fe0a3333e5db49e74c982bcfef9737b65cc78 [4]

[1] This one:

> V511 The sizeof() operator returns size of the pointer, and not of the array, in 'sizeof ((domain))' expression. wbinfo.c 124

I am not convinced it is correct, but in any case fstrcpy() has changed in the meantime.


[2] needs a patch!


[3] This affects md2, rc2, and rand-fortuna in heimdal/hcrypto:

> V597 The compiler could delete the 'memset' function call, which is used to flush 'x' buffer. The RtlSecureZeroMemory() function should be used to erase the private data. md2.c 91

RtlSecureZeroMemory() is a windows word for memset_s(). I think the concern is valid; OTOH md2, rc2, fortuna. Maybe these will be fixed by a Heimdal update.


[4] I didn't check all the issues the '#add' section, which cover some of the heimdal/hcrypto files.



Status: NEARLY_FIXED.
Comment 2 Samba QA Contact 2022-01-26 12:40:04 UTC
This bug was referenced in samba master:

891201f154a2ca05b7fc8ec78492a79ee0bddafe
Comment 3 Douglas Bagnall 2022-01-26 23:00:40 UTC
As far as I can tell, the last remaining bug in this nebula was fixed in
891201f154a2ca05b7fc8ec78492a79ee0bddafe.

That is not counting the memsets in heimdal, but heimdal is in third_party and we don't patch there!