text: /*
   * This file is a part of SMalloc.
   * SMalloc is MIT licensed.
   * Copyright (c) 2017 Andrey Rys.
   */
  
  #include "smalloc_i.h"
  
  static int smalloc_check_bounds(struct smalloc_pool *spool, struct smalloc_hdr *shdr)
  {
  	if (!spool) return 0;
  	if (CHAR_PTR(shdr) >= CHAR_PTR(spool->pool)
  	&& CHAR_PTR(shdr) <= (CHAR_PTR(spool->pool)+spool->pool_size))
  		return 1;
  	return 0;
  }
  
  static int smalloc_valid_tag(struct smalloc_hdr *shdr)
  {
  	char *s;
  	uintptr_t r = smalloc_mktag(shdr);
  	size_t x;
  
  	if (shdr->tag == r) {
  		s = CHAR_PTR(HEADER_TO_USER(shdr));
  		s += shdr->usz;
  		for (x = 0; x < sizeof(struct smalloc_hdr); x += sizeof(uintptr_t)) {
  			r = smalloc_uinthash(r);
  			if (memcmp(s+x, &r, sizeof(uintptr_t)) != 0) return 0;
  		}
  		s += x; x = 0;
  		while (x < shdr->rsz - shdr->usz) {
  			if (s[x] != '\xFF') return 0;
  			x++;
  		}
  		return 1;
  	}
  	return 0;
  }
  
  static void smalloc_do_crash(struct smalloc_pool *spool, const void *p)
  {
  	char *c = NULL;
  	*c = 'X';
  }
  
  smalloc_ub_handler smalloc_UB = smalloc_do_crash;
  
  void sm_set_ub_handler(smalloc_ub_handler handler)
  {
  	if (!handler) smalloc_UB = smalloc_do_crash;
  	else smalloc_UB = handler;
  }
  
  int smalloc_is_alloc(struct smalloc_pool *spool, struct smalloc_hdr *shdr)
  {
  	if (!smalloc_check_bounds(spool, shdr)) return 0;
  	if (shdr->rsz == 0) return 0;
  	if (shdr->rsz > SIZE_MAX) return 0;
  	if (shdr->usz > SIZE_MAX) return 0;
  	if (shdr->usz > shdr->rsz) return 0;
  	if (shdr->rsz % HEADER_SZ) return 0;
  	if (!smalloc_valid_tag(shdr)) return 0;
    if (!smalloc_check_magic(shdr)) return 0;
  	return 1;
  }
  
  int smalloc_check_magic(struct smalloc_hdr* shdr) {
    return shdr->sm_magic == SM_MAGIC;
  }
  