Half slabs work exactly as expected:
```
[08:10:33 INFO]: *** Hitbox for block CraftBlock{chunk=CraftChunk{x=6z=21},x=109,y=72,z=339,type=STEP,data=0}
[08:10:33 INFO]:   109.0,72.0,339.0 => 110.0,72.5,340.0
```

Stairs are a little strange:
```
[08:10:50 INFO]: *** Hitbox for block CraftBlock{chunk=CraftChunk{x=6z=21},x=103,y=74,z=345,type=SMOOTH_STAIRS,data=5}
[08:10:50 INFO]:   103.5,74.5,345.5 => 104.0,75.0,346.0
```

Note that block.getHitbox() is just returning what the NMS Block class computes, given the block's type and data.  The actual hitbox computation for stairs is done in the NMS BlockStairs.class:
```
public void updateShape(IBlockAccess paramIBlockAccess, int paramInt1, int paramInt2, int paramInt3)
  {
    if (this.N)
      a(0.5F * (this.O % 2), 0.5F * (this.O / 2 % 2), 0.5F * (this.O / 4 % 2), 0.5F + 0.5F * (this.O % 2), 0.5F + 0.5F * (this.O / 2 % 2), 0.5F + 0.5F * (this.O / 4 % 2));
    else
      a(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
  }
```

My testing shows that stairs always seem to have a hitbox of (X+0.5,Y+0.5,Z+0.5)->(X+1,Y+1,Z+1), regardless of stair orientation (horizontal or vertical).  This does look a bit odd, but as I said, it's what the server is calculating.